On 13/12/2024 10:42, Markuss Broks wrote:
Hi Krzysztof,It's fine then.
On 12/13/24 9:49 AM, Krzysztof Kozlowski wrote:
On 12/12/2024 22:09, Markuss Broks wrote:This is not compatible with Dallas Semi 1-Wire bus. There are several
Add a driver for Samsung SPEEDY serial bus host controller.I did not check that much but this looks like 1wire for which we have
SPEEDY is a proprietary 1 wire serial bus used by Samsung
in various devices (usually mobile), like Samsung Galaxy
phones. It is usually used for connecting PMIC or various
other peripherals, like audio codecs or RF components.
This bus can address at most 1MiB (4 bit device address,
8 bit registers per device, 8 bit wide registers:
256*256*16 = 1MiB of address space.
Co-developed-by: Maksym Holovach <nergzd@xxxxxxxxxxxxx>
Signed-off-by: Maksym Holovach <nergzd@xxxxxxxxxxxxx>
Signed-off-by: Markuss Broks <markuss.broks@xxxxxxxxx>
---
drivers/soc/samsung/Kconfig | 13 +
drivers/soc/samsung/Makefile | 2 +
drivers/soc/samsung/exynos-speedy.c | 457 ++++++++++++++++++++++++++++++
include/linux/soc/samsung/exynos-speedy.h | 56 ++++
4 files changed, 528 insertions(+)
diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index 1a5dfdc978dc4069eb71c4e8eada7ff1913b86b3..a38150fc9999ded1e1e93e2a9ef43b88175d34bd 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -49,6 +49,19 @@ config EXYNOS_PMU_ARM_DRIVERS
bool "Exynos PMU ARMv7-specific driver extensions" if COMPILE_TEST
depends on EXYNOS_PMU
+config EXYNOS_SPEEDY
+ tristate "Exynos SPEEDY host controller driver"
+ depends on ARCH_EXYNOS || COMPILE_TEST
+ depends on OF
+ depends on REGMAP_MMIO
+ help
+ Enable support for Exynos SPEEDY host controller block.
+ SPEEDY is a 1 wire proprietary Samsung serial bus, found in
+ modern Samsung Exynos SoCs, like Exynos8895 and newer.
subsystem. Please investigate more and figure out the differences.
differences but the phy level is not compatible, looking at the Samsung
patent. [1] The most obvious difference is that 1-Wire is discoverable,
and this bus isn't. I'm pretty sure this is Samsung's own solution to a
serial interface through only one wire.
The function speedy_get_device uses this to match the compatible, do I+This is never at top of the file, but immediately before driver
+ Select this if you have a Samsung Exynos device which uses
+ SPEEDY bus.
+
+
+/* SPEEDY_PACKET_GAP_TIME register bits */
+#define SPEEDY_FIFO_TX_ALMOST_EMPTY (1 << 4)
+#define SPEEDY_FIFO_RX_ALMOST_FULL (1 << 8)
+#define SPEEDY_FSM_INIT (1 << 1)
+#define SPEEDY_FSM_TX_CMD (1 << 2)
+#define SPEEDY_FSM_STANDBY (1 << 3)
+#define SPEEDY_FSM_DATA (1 << 4)
+#define SPEEDY_FSM_TIMEOUT (1 << 5)
+#define SPEEDY_FSM_TRANS_DONE (1 << 6)
+#define SPEEDY_FSM_IO_RX_STAT_MASK (3 << 7)
+#define SPEEDY_FSM_IO_TX_IDLE (1 << 9)
+#define SPEEDY_FSM_IO_TX_GET_PACKET (1 << 10)
+#define SPEEDY_FSM_IO_TX_PACKET (1 << 11)
+#define SPEEDY_FSM_IO_TX_DONE (1 << 12)
+
+#define SPEEDY_RX_LENGTH(n) ((n) << 0)
+#define SPEEDY_TX_LENGTH(n) ((n) << 8)
+
+#define SPEEDY_DEVICE(x) ((x & 0xf) << 15)
+#define SPEEDY_ADDRESS(x) ((x & 0xff) << 7)
+
+static const struct of_device_id speedy_match[] = {
+ { .compatible = "samsung,exynos9810-speedy" },
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, speedy_match);
structure. Look at other drivers.
just leave the prototype here?
1. Entire speedy_get_device() is unused so it will be removed.
2. Even if it stays, speedy_get_device() is not supposed to match
anything. How are you supposed to use Samsung PMIC on different
controller? These things should not be tied.
+
+static const struct regmap_config speedy_map_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+};
...
Post entire series, so we see users of this API. If you post API withoutThis is intended to be used with other device drivers, this driver in+ cmd = SPEEDY_ACCESS_RANDOM | SPEEDY_DIRECTION_READ |Nope, drop, unused.
+ SPEEDY_DEVICE(reg) | SPEEDY_ADDRESS(addr);
+
+ int_ctl = SPEEDY_TRANSFER_DONE_EN | SPEEDY_FIFO_RX_ALMOST_FULL_EN |
+ SPEEDY_RX_FIFO_INT_TRAILER_EN | SPEEDY_RX_MODEBIT_ERR_EN |
+ SPEEDY_RX_GLITCH_ERR_EN | SPEEDY_RX_ENDBIT_ERR_EN |
+ SPEEDY_REMOTE_RESET_REQ_EN;
+
+ ret = speedy_int_clear(speedy);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(speedy->map, SPEEDY_INT_ENABLE, int_ctl);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(speedy->map, SPEEDY_CMD, cmd);
+ if (ret)
+ return ret;
+
+ /* Wait for xfer done */
+ ret = regmap_read_poll_timeout(speedy->map, SPEEDY_INT_STATUS, int_status,
+ int_status & SPEEDY_TRANSFER_DONE, 5000, 50000);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(speedy->map, SPEEDY_RX_DATA, val);
+ if (ret)
+ return ret;
+
+ ret = speedy_int_clear(speedy);
+
+ mutex_unlock(&speedy->io_lock);
+
+ return ret;
+}
+
+int exynos_speedy_read(const struct speedy_device *device, u32 addr, u32 *val)
+{
+ return _speedy_read(device->speedy, device->reg, addr, val);
+}
+EXPORT_SYMBOL_GPL(exynos_speedy_read);
itself doesn't do anything, it only configures the controller and makes
it ready for transmitting data, it's other drivers that will come (e.g.
S2MPS18 PMIC, which uses SPEEDY for communication with the SoC) that
will utilize those functions.
users, it won't be accepted simply because there are no users and we do
not want dead, unused code.
Anyway we must see how you intend to use that interface to properly
review it.
+
+/**
+ * _speedy_write() - internal speedy write operation
+ * @speedy: pointer to speedy controller struct
+ * @reg: address of device on the bus
+ * @addr: address to write
+ * @val: value to write
+ *
...
This needs to be proper bus with proper speedy_driver clients. See howSame here, please clarify how this should be handled. This driver+}Drop the header, not used.
+
+static struct platform_driver speedy_driver = {
+ .probe = speedy_probe,
+ .driver = {
+ .name = "exynos-speedy",
+ .of_match_table = speedy_match,
+ },
+};
+
+module_platform_driver(speedy_driver);
+
+MODULE_DESCRIPTION("Samsung Exynos SPEEDY host controller driver");
+MODULE_AUTHOR("Markuss Broks <markuss.broks@xxxxxxxxx>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/soc/samsung/exynos-speedy.h b/include/linux/soc/samsung/exynos-speedy.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2857d65d3b50927373866dd8ae1c47e98af6d7b
--- /dev/null
+++ b/include/linux/soc/samsung/exynos-speedy.h
implements the devm_speedy_get_device and read/write functions for its
child devices in that header, future drivers for e.g. PMIC would use
this header and call devm_speedy_get_device to get a speedy_device
pointer and then use read/write functions to read/write from the bus.
other buses - struct bus_type. Recent example of bus using platform
drivers for devices would be pwrseq (power/sequence). Not so old other
bus using its own xxx_driver for devices could be cxl or ffa (arm_ffa).
This current non-bus approach, could also work if this is really Samsung
specific. See memory/ for examples of MMIO buses and MMIO clients.
I don't know good examples of non-MMIO buses not using bus_type and I am
not sure whether this is accepted in general. I'll ask on IRC, maybe
someone will give some hints.
Best regards,
Krzysztof