332 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// Copyright (C) 2020 BAIKAL ELECTRONICS, JSC4//5// Authors:6// Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>7// Serge Semin <Sergey.Semin@baikalelectronics.ru>8//9// Baikal-T1 DW APB SPI and System Boot SPI driver10//11 12#include <linux/clk.h>13#include <linux/cpumask.h>14#include <linux/err.h>15#include <linux/interrupt.h>16#include <linux/module.h>17#include <linux/mux/consumer.h>18#include <linux/of.h>19#include <linux/of_platform.h>20#include <linux/platform_device.h>21#include <linux/pm_runtime.h>22#include <linux/property.h>23#include <linux/slab.h>24#include <linux/spi/spi-mem.h>25#include <linux/spi/spi.h>26 27#include "spi-dw.h"28 29#define BT1_BOOT_DIRMAP 030#define BT1_BOOT_REGS 131 32struct dw_spi_bt1 {33 struct dw_spi dws;34 struct clk *clk;35 struct mux_control *mux;36 37#ifdef CONFIG_SPI_DW_BT1_DIRMAP38 void __iomem *map;39 resource_size_t map_len;40#endif41};42#define to_dw_spi_bt1(_ctlr) \43 container_of(spi_controller_get_devdata(_ctlr), struct dw_spi_bt1, dws)44 45typedef int (*dw_spi_bt1_init_cb)(struct platform_device *pdev,46 struct dw_spi_bt1 *dwsbt1);47 48#ifdef CONFIG_SPI_DW_BT1_DIRMAP49 50static int dw_spi_bt1_dirmap_create(struct spi_mem_dirmap_desc *desc)51{52 struct dw_spi_bt1 *dwsbt1 = to_dw_spi_bt1(desc->mem->spi->controller);53 54 if (!dwsbt1->map ||55 !dwsbt1->dws.mem_ops.supports_op(desc->mem, &desc->info.op_tmpl))56 return -EOPNOTSUPP;57 58 if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)59 return -EOPNOTSUPP;60 61 /*62 * Make sure the requested region doesn't go out of the physically63 * mapped flash memory bounds.64 */65 if (desc->info.offset + desc->info.length > dwsbt1->map_len)66 return -EINVAL;67 68 return 0;69}70 71/*72 * Directly mapped SPI memory region is only accessible in the dword chunks.73 * That's why we have to create a dedicated read-method to copy data from there74 * to the passed buffer.75 */76static void dw_spi_bt1_dirmap_copy_from_map(void *to, void __iomem *from, size_t len)77{78 size_t shift, chunk;79 u32 data;80 81 /*82 * We split the copying up into the next three stages: unaligned head,83 * aligned body, unaligned tail.84 */85 shift = (size_t)from & 0x3;86 if (shift) {87 chunk = min_t(size_t, 4 - shift, len);88 data = readl_relaxed(from - shift);89 memcpy(to, (char *)&data + shift, chunk);90 from += chunk;91 to += chunk;92 len -= chunk;93 }94 95 while (len >= 4) {96 data = readl_relaxed(from);97 memcpy(to, &data, 4);98 from += 4;99 to += 4;100 len -= 4;101 }102 103 if (len) {104 data = readl_relaxed(from);105 memcpy(to, &data, len);106 }107}108 109static ssize_t dw_spi_bt1_dirmap_read(struct spi_mem_dirmap_desc *desc,110 u64 offs, size_t len, void *buf)111{112 struct dw_spi_bt1 *dwsbt1 = to_dw_spi_bt1(desc->mem->spi->controller);113 struct dw_spi *dws = &dwsbt1->dws;114 struct spi_mem *mem = desc->mem;115 struct dw_spi_cfg cfg;116 int ret;117 118 /*119 * Make sure the requested operation length is valid. Truncate the120 * length if it's greater than the length of the MMIO region.121 */122 if (offs >= dwsbt1->map_len || !len)123 return 0;124 125 len = min_t(size_t, len, dwsbt1->map_len - offs);126 127 /* Collect the controller configuration required by the operation */128 cfg.tmode = DW_SPI_CTRLR0_TMOD_EPROMREAD;129 cfg.dfs = 8;130 cfg.ndf = 4;131 cfg.freq = mem->spi->max_speed_hz;132 133 /* Make sure the corresponding CS is de-asserted on transmission */134 dw_spi_set_cs(mem->spi, false);135 136 dw_spi_enable_chip(dws, 0);137 138 dw_spi_update_config(dws, mem->spi, &cfg);139 140 dw_spi_umask_intr(dws, DW_SPI_INT_RXFI);141 142 dw_spi_enable_chip(dws, 1);143 144 /*145 * Enable the transparent mode of the System Boot Controller.146 * The SPI core IO should have been locked before calling this method147 * so noone would be touching the controller' registers during the148 * dirmap operation.149 */150 ret = mux_control_select(dwsbt1->mux, BT1_BOOT_DIRMAP);151 if (ret)152 return ret;153 154 dw_spi_bt1_dirmap_copy_from_map(buf, dwsbt1->map + offs, len);155 156 mux_control_deselect(dwsbt1->mux);157 158 dw_spi_set_cs(mem->spi, true);159 160 ret = dw_spi_check_status(dws, true);161 162 return ret ?: len;163}164 165#endif /* CONFIG_SPI_DW_BT1_DIRMAP */166 167static int dw_spi_bt1_std_init(struct platform_device *pdev,168 struct dw_spi_bt1 *dwsbt1)169{170 struct dw_spi *dws = &dwsbt1->dws;171 172 dws->irq = platform_get_irq(pdev, 0);173 if (dws->irq < 0)174 return dws->irq;175 176 dws->num_cs = 4;177 178 /*179 * Baikal-T1 Normal SPI Controllers don't always keep up with full SPI180 * bus speed especially when it comes to the concurrent access to the181 * APB bus resources. Thus we have no choice but to set a constraint on182 * the SPI bus frequency for the memory operations which require to183 * read/write data as fast as possible.184 */185 dws->max_mem_freq = 20000000U;186 187 dw_spi_dma_setup_generic(dws);188 189 return 0;190}191 192static int dw_spi_bt1_sys_init(struct platform_device *pdev,193 struct dw_spi_bt1 *dwsbt1)194{195 struct resource *mem __maybe_unused;196 struct dw_spi *dws = &dwsbt1->dws;197 198 /*199 * Baikal-T1 System Boot Controller is equipped with a mux, which200 * switches between the directly mapped SPI flash access mode and201 * IO access to the DW APB SSI registers. Note the mux controller202 * must be setup to preserve the registers being accessible by default203 * (on idle-state).204 */205 dwsbt1->mux = devm_mux_control_get(&pdev->dev, NULL);206 if (IS_ERR(dwsbt1->mux))207 return PTR_ERR(dwsbt1->mux);208 209 /*210 * Directly mapped SPI flash memory is a 16MB MMIO region, which can be211 * used to access a peripheral memory device just by reading/writing212 * data from/to it. Note the system APB bus will stall during each IO213 * from/to the dirmap region until the operation is finished. So don't214 * use it concurrently with time-critical tasks (like the SPI memory215 * operations implemented in the DW APB SSI driver).216 */217#ifdef CONFIG_SPI_DW_BT1_DIRMAP218 mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);219 if (mem) {220 dwsbt1->map = devm_ioremap_resource(&pdev->dev, mem);221 if (!IS_ERR(dwsbt1->map)) {222 dwsbt1->map_len = resource_size(mem);223 dws->mem_ops.dirmap_create = dw_spi_bt1_dirmap_create;224 dws->mem_ops.dirmap_read = dw_spi_bt1_dirmap_read;225 } else {226 dwsbt1->map = NULL;227 }228 }229#endif /* CONFIG_SPI_DW_BT1_DIRMAP */230 231 /*232 * There is no IRQ, no DMA and just one CS available on the System Boot233 * SPI controller.234 */235 dws->irq = IRQ_NOTCONNECTED;236 dws->num_cs = 1;237 238 /*239 * Baikal-T1 System Boot SPI Controller doesn't keep up with the full240 * SPI bus speed due to relatively slow APB bus and races for it'241 * resources from different CPUs. The situation is worsen by a small242 * FIFOs depth (just 8 words). It works better in a single CPU mode243 * though, but still tends to be not fast enough at low CPU244 * frequencies.245 */246 if (num_possible_cpus() > 1)247 dws->max_mem_freq = 10000000U;248 else249 dws->max_mem_freq = 20000000U;250 251 return 0;252}253 254static int dw_spi_bt1_probe(struct platform_device *pdev)255{256 dw_spi_bt1_init_cb init_func;257 struct dw_spi_bt1 *dwsbt1;258 struct resource *mem;259 struct dw_spi *dws;260 int ret;261 262 dwsbt1 = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_bt1), GFP_KERNEL);263 if (!dwsbt1)264 return -ENOMEM;265 266 dws = &dwsbt1->dws;267 268 dws->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);269 if (IS_ERR(dws->regs))270 return PTR_ERR(dws->regs);271 272 dws->paddr = mem->start;273 274 dwsbt1->clk = devm_clk_get_enabled(&pdev->dev, NULL);275 if (IS_ERR(dwsbt1->clk))276 return PTR_ERR(dwsbt1->clk);277 278 dws->bus_num = pdev->id;279 dws->reg_io_width = 4;280 dws->max_freq = clk_get_rate(dwsbt1->clk);281 if (!dws->max_freq)282 return -EINVAL;283 284 init_func = device_get_match_data(&pdev->dev);285 ret = init_func(pdev, dwsbt1);286 if (ret)287 return ret;288 289 pm_runtime_enable(&pdev->dev);290 291 ret = dw_spi_add_host(&pdev->dev, dws);292 if (ret) {293 pm_runtime_disable(&pdev->dev);294 return ret;295 }296 297 platform_set_drvdata(pdev, dwsbt1);298 299 return 0;300}301 302static void dw_spi_bt1_remove(struct platform_device *pdev)303{304 struct dw_spi_bt1 *dwsbt1 = platform_get_drvdata(pdev);305 306 dw_spi_remove_host(&dwsbt1->dws);307 308 pm_runtime_disable(&pdev->dev);309}310 311static const struct of_device_id dw_spi_bt1_of_match[] = {312 { .compatible = "baikal,bt1-ssi", .data = dw_spi_bt1_std_init},313 { .compatible = "baikal,bt1-sys-ssi", .data = dw_spi_bt1_sys_init},314 { }315};316MODULE_DEVICE_TABLE(of, dw_spi_bt1_of_match);317 318static struct platform_driver dw_spi_bt1_driver = {319 .probe = dw_spi_bt1_probe,320 .remove_new = dw_spi_bt1_remove,321 .driver = {322 .name = "bt1-sys-ssi",323 .of_match_table = dw_spi_bt1_of_match,324 },325};326module_platform_driver(dw_spi_bt1_driver);327 328MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");329MODULE_DESCRIPTION("Baikal-T1 System Boot SPI Controller driver");330MODULE_LICENSE("GPL v2");331MODULE_IMPORT_NS(SPI_DW_CORE);332