probe: fix SWDIO line idle state and export low-level functions

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
diff --git a/src/probe.c b/src/probe.c
index 3396796..2fe9672 100644
--- a/src/probe.c
+++ b/src/probe.c
@@ -63,6 +63,8 @@
 
     // PIO offset
     uint offset;
+
+    uint cached_freq_khz;
 };
 
 static struct _probe probe;
@@ -87,20 +89,23 @@
 };
 
 void probe_set_swclk_freq(uint freq_khz) {
-    picoprobe_info("Set swclk freq %dKHz\n", freq_khz);
-    uint clk_sys_freq_khz = clock_get_hz(clk_sys) / 1000;
-    // Worked out with saleae
-    uint32_t divider = clk_sys_freq_khz / freq_khz / 2;
-    pio_sm_set_clkdiv_int_frac(pio0, PROBE_SM, divider, 0);
+    if (freq_khz != probe.cached_freq_khz) {
+        uint clk_sys_freq_khz = clock_get_hz(clk_sys) / 1000;
+        picoprobe_info("Set swclk freq %dKHz sysclk %dkHz\n", freq_khz, clk_sys_freq_khz);
+        // Worked out with saleae
+        uint32_t divider = clk_sys_freq_khz / freq_khz / 2;
+        pio_sm_set_clkdiv_int_frac(pio0, PROBE_SM, divider, 0);
+        probe.cached_freq_khz = freq_khz;
+    }
 }
 
-static inline void probe_assert_reset(bool state)
+void probe_assert_reset(bool state)
 {
     /* Change the direction to out to drive pin to 0 or to in to emulate open drain */
     gpio_set_dir(PROBE_PIN_RESET, state);
 }
 
-static inline void probe_write_bits(uint bit_count, uint8_t data_byte) {
+void probe_write_bits(uint bit_count, uint8_t data_byte) {
     DEBUG_PINS_SET(probe_timing, DBG_PIN_WRITE);
     pio_sm_put_blocking(pio0, PROBE_SM, bit_count - 1);
     pio_sm_put_blocking(pio0, PROBE_SM, data_byte);
@@ -112,7 +117,7 @@
     DEBUG_PINS_CLR(probe_timing, DBG_PIN_WRITE);
 }
 
-static inline uint8_t probe_read_bits(uint bit_count) {
+uint8_t probe_read_bits(uint bit_count) {
     DEBUG_PINS_SET(probe_timing, DBG_PIN_READ);
     pio_sm_put_blocking(pio0, PROBE_SM, bit_count - 1);
     uint32_t data = pio_sm_get_blocking(pio0, PROBE_SM);
@@ -127,12 +132,12 @@
     return data_shifted;
 }
 
-static void probe_read_mode(void) {
+void probe_read_mode(void) {
     pio_sm_exec(pio0, PROBE_SM, pio_encode_jmp(probe.offset + probe_offset_in_posedge));
     while(pio0->dbg_padoe & (1 << PROBE_PIN_SWDIO));
 }
 
-static void probe_write_mode(void) {
+void probe_write_mode(void) {
     pio_sm_exec(pio0, PROBE_SM, pio_encode_jmp(probe.offset + probe_offset_out_negedge));
     while(!(pio0->dbg_padoe & (1 << PROBE_PIN_SWDIO)));
 }
@@ -183,6 +188,13 @@
     probe_write_mode();
 }
 
+void probe_deinit(void)
+{
+  probe_read_mode();
+  pio_sm_set_enabled(pio0, PROBE_SM, 0);
+  pio_remove_program(pio0, &probe_program, probe.offset);
+}
+
 void probe_handle_read(uint total_bits) {
     picoprobe_debug("Read %d bits\n", total_bits);
     probe_read_mode();
diff --git a/src/probe.h b/src/probe.h
index 2474a38..69810db 100644
--- a/src/probe.h
+++ b/src/probe.h
@@ -26,7 +26,17 @@
 #ifndef PROBE_H_
 #define PROBE_H_
 
+void probe_set_swclk_freq(uint freq_khz);
+void probe_write_bits(uint bit_count, uint8_t data_byte);
+uint8_t probe_read_bits(uint bit_count);
+
+void probe_read_mode(void);
+void probe_write_mode(void);
+
+void probe_handle_read(uint total_bits);
+void probe_handle_write(uint8_t *data, uint total_bits);
+
 void probe_task(void);
 void probe_init(void);
-
+void probe_deinit(void);
 #endif
\ No newline at end of file
diff --git a/src/probe.pio b/src/probe.pio
index 920a3a5..4a242ba 100644
--- a/src/probe.pio
+++ b/src/probe.pio
@@ -34,7 +34,7 @@
 out_negedge_bitloop:
     out pins, 1                  side 0x0 ; clock data out on falling edge
     jmp  x-- out_negedge_bitloop side 0x1 ; data is present for posedge
-    set pins, 0                  side 0x0 ; Drive data low
+    set pins, 1                  side 0x0 ; Drive data high (idle bus state)
     push                                 ; Push to rx fifo just so processor knows when done
     jmp out_negedge                      ; Wait for next transaction