^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Linux driver for RPC-IF HyperFlash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2019-2020 Cogent Embedded, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mtd/hyperbus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mtd/mtd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mux/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <memory/renesas-rpc-if.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct rpcif_hyperbus {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct rpcif rpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct hyperbus_ctlr ctlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct hyperbus_device hbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static const struct rpcif_op rpcif_op_tmpl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .cmd = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .buswidth = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) .ddr = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .ocmd = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) .buswidth = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) .ddr = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .addr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .nbytes = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .buswidth = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .ddr = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .buswidth = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .ddr = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static void rpcif_hb_prepare_read(struct rpcif *rpc, void *to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned long from, ssize_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct rpcif_op op = rpcif_op_tmpl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) op.cmd.opcode = HYPERBUS_RW_READ | HYPERBUS_AS_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) op.addr.val = from >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) op.dummy.buswidth = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) op.dummy.ncycles = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) op.data.dir = RPCIF_DATA_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) op.data.nbytes = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) op.data.buf.in = to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) rpcif_prepare(rpc, &op, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void rpcif_hb_prepare_write(struct rpcif *rpc, unsigned long to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) void *from, ssize_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct rpcif_op op = rpcif_op_tmpl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) op.cmd.opcode = HYPERBUS_RW_WRITE | HYPERBUS_AS_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) op.addr.val = to >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) op.data.dir = RPCIF_DATA_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) op.data.nbytes = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) op.data.buf.out = from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) rpcif_prepare(rpc, &op, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static u16 rpcif_hb_read16(struct hyperbus_device *hbdev, unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct rpcif_hyperbus *hyperbus =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) container_of(hbdev, struct rpcif_hyperbus, hbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) map_word data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) rpcif_hb_prepare_read(&hyperbus->rpc, &data, addr, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) rpcif_manual_xfer(&hyperbus->rpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return data.x[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static void rpcif_hb_write16(struct hyperbus_device *hbdev, unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct rpcif_hyperbus *hyperbus =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) container_of(hbdev, struct rpcif_hyperbus, hbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) rpcif_hb_prepare_write(&hyperbus->rpc, addr, &data, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) rpcif_manual_xfer(&hyperbus->rpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void rpcif_hb_copy_from(struct hyperbus_device *hbdev, void *to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned long from, ssize_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct rpcif_hyperbus *hyperbus =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) container_of(hbdev, struct rpcif_hyperbus, hbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) rpcif_hb_prepare_read(&hyperbus->rpc, to, from, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) rpcif_dirmap_read(&hyperbus->rpc, from, len, to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static const struct hyperbus_ops rpcif_hb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .read16 = rpcif_hb_read16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .write16 = rpcif_hb_write16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .copy_from = rpcif_hb_copy_from,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int rpcif_hb_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct rpcif_hyperbus *hyperbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) hyperbus = devm_kzalloc(dev, sizeof(*hyperbus), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (!hyperbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) error = rpcif_sw_init(&hyperbus->rpc, pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) platform_set_drvdata(pdev, hyperbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rpcif_enable_rpm(&hyperbus->rpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) rpcif_hw_init(&hyperbus->rpc, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) hyperbus->hbdev.map.size = hyperbus->rpc.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) hyperbus->hbdev.map.virt = hyperbus->rpc.dirmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) hyperbus->ctlr.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) hyperbus->ctlr.ops = &rpcif_hb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) hyperbus->hbdev.ctlr = &hyperbus->ctlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) hyperbus->hbdev.np = of_get_next_child(pdev->dev.parent->of_node, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) error = hyperbus_register_device(&hyperbus->hbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) rpcif_disable_rpm(&hyperbus->rpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int rpcif_hb_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct rpcif_hyperbus *hyperbus = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int error = hyperbus_unregister_device(&hyperbus->hbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) rpcif_disable_rpm(&hyperbus->rpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static struct platform_driver rpcif_platform_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .probe = rpcif_hb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .remove = rpcif_hb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .name = "rpc-if-hyperflash",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) module_platform_driver(rpcif_platform_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) MODULE_DESCRIPTION("Renesas RPC-IF HyperFlash driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) MODULE_LICENSE("GPL v2");