0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/clk.h>
0013 #include <linux/cpumask.h>
0014 #include <linux/err.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/module.h>
0017 #include <linux/mux/consumer.h>
0018 #include <linux/of.h>
0019 #include <linux/of_platform.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/pm_runtime.h>
0022 #include <linux/property.h>
0023 #include <linux/slab.h>
0024 #include <linux/spi/spi-mem.h>
0025 #include <linux/spi/spi.h>
0026
0027 #include "spi-dw.h"
0028
0029 #define BT1_BOOT_DIRMAP 0
0030 #define BT1_BOOT_REGS 1
0031
0032 struct dw_spi_bt1 {
0033 struct dw_spi dws;
0034 struct clk *clk;
0035 struct mux_control *mux;
0036
0037 #ifdef CONFIG_SPI_DW_BT1_DIRMAP
0038 void __iomem *map;
0039 resource_size_t map_len;
0040 #endif
0041 };
0042 #define to_dw_spi_bt1(_ctlr) \
0043 container_of(spi_controller_get_devdata(_ctlr), struct dw_spi_bt1, dws)
0044
0045 typedef int (*dw_spi_bt1_init_cb)(struct platform_device *pdev,
0046 struct dw_spi_bt1 *dwsbt1);
0047
0048 #ifdef CONFIG_SPI_DW_BT1_DIRMAP
0049
0050 static int dw_spi_bt1_dirmap_create(struct spi_mem_dirmap_desc *desc)
0051 {
0052 struct dw_spi_bt1 *dwsbt1 = to_dw_spi_bt1(desc->mem->spi->controller);
0053
0054 if (!dwsbt1->map ||
0055 !dwsbt1->dws.mem_ops.supports_op(desc->mem, &desc->info.op_tmpl))
0056 return -EOPNOTSUPP;
0057
0058
0059
0060
0061
0062 if (desc->info.offset + desc->info.length > dwsbt1->map_len ||
0063 desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
0064 return -EOPNOTSUPP;
0065
0066 return 0;
0067 }
0068
0069
0070
0071
0072
0073
0074 static void dw_spi_bt1_dirmap_copy_from_map(void *to, void __iomem *from, size_t len)
0075 {
0076 size_t shift, chunk;
0077 u32 data;
0078
0079
0080
0081
0082
0083 shift = (size_t)from & 0x3;
0084 if (shift) {
0085 chunk = min_t(size_t, 4 - shift, len);
0086 data = readl_relaxed(from - shift);
0087 memcpy(to, (char *)&data + shift, chunk);
0088 from += chunk;
0089 to += chunk;
0090 len -= chunk;
0091 }
0092
0093 while (len >= 4) {
0094 data = readl_relaxed(from);
0095 memcpy(to, &data, 4);
0096 from += 4;
0097 to += 4;
0098 len -= 4;
0099 }
0100
0101 if (len) {
0102 data = readl_relaxed(from);
0103 memcpy(to, &data, len);
0104 }
0105 }
0106
0107 static ssize_t dw_spi_bt1_dirmap_read(struct spi_mem_dirmap_desc *desc,
0108 u64 offs, size_t len, void *buf)
0109 {
0110 struct dw_spi_bt1 *dwsbt1 = to_dw_spi_bt1(desc->mem->spi->controller);
0111 struct dw_spi *dws = &dwsbt1->dws;
0112 struct spi_mem *mem = desc->mem;
0113 struct dw_spi_cfg cfg;
0114 int ret;
0115
0116
0117
0118
0119
0120 if (offs >= dwsbt1->map_len || !len)
0121 return 0;
0122
0123 len = min_t(size_t, len, dwsbt1->map_len - offs);
0124
0125
0126 cfg.tmode = DW_SPI_CTRLR0_TMOD_EPROMREAD;
0127 cfg.dfs = 8;
0128 cfg.ndf = 4;
0129 cfg.freq = mem->spi->max_speed_hz;
0130
0131
0132 dw_spi_set_cs(mem->spi, false);
0133
0134 dw_spi_enable_chip(dws, 0);
0135
0136 dw_spi_update_config(dws, mem->spi, &cfg);
0137
0138 dw_spi_umask_intr(dws, DW_SPI_INT_RXFI);
0139
0140 dw_spi_enable_chip(dws, 1);
0141
0142
0143
0144
0145
0146
0147
0148 ret = mux_control_select(dwsbt1->mux, BT1_BOOT_DIRMAP);
0149 if (ret)
0150 return ret;
0151
0152 dw_spi_bt1_dirmap_copy_from_map(buf, dwsbt1->map + offs, len);
0153
0154 mux_control_deselect(dwsbt1->mux);
0155
0156 dw_spi_set_cs(mem->spi, true);
0157
0158 ret = dw_spi_check_status(dws, true);
0159
0160 return ret ?: len;
0161 }
0162
0163 #endif
0164
0165 static int dw_spi_bt1_std_init(struct platform_device *pdev,
0166 struct dw_spi_bt1 *dwsbt1)
0167 {
0168 struct dw_spi *dws = &dwsbt1->dws;
0169
0170 dws->irq = platform_get_irq(pdev, 0);
0171 if (dws->irq < 0)
0172 return dws->irq;
0173
0174 dws->num_cs = 4;
0175
0176
0177
0178
0179
0180
0181
0182
0183 dws->max_mem_freq = 20000000U;
0184
0185 dw_spi_dma_setup_generic(dws);
0186
0187 return 0;
0188 }
0189
0190 static int dw_spi_bt1_sys_init(struct platform_device *pdev,
0191 struct dw_spi_bt1 *dwsbt1)
0192 {
0193 struct resource *mem __maybe_unused;
0194 struct dw_spi *dws = &dwsbt1->dws;
0195
0196
0197
0198
0199
0200
0201
0202
0203 dwsbt1->mux = devm_mux_control_get(&pdev->dev, NULL);
0204 if (IS_ERR(dwsbt1->mux))
0205 return PTR_ERR(dwsbt1->mux);
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 #ifdef CONFIG_SPI_DW_BT1_DIRMAP
0216 mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0217 if (mem) {
0218 dwsbt1->map = devm_ioremap_resource(&pdev->dev, mem);
0219 if (!IS_ERR(dwsbt1->map)) {
0220 dwsbt1->map_len = resource_size(mem);
0221 dws->mem_ops.dirmap_create = dw_spi_bt1_dirmap_create;
0222 dws->mem_ops.dirmap_read = dw_spi_bt1_dirmap_read;
0223 } else {
0224 dwsbt1->map = NULL;
0225 }
0226 }
0227 #endif
0228
0229
0230
0231
0232
0233 dws->irq = IRQ_NOTCONNECTED;
0234 dws->num_cs = 1;
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 if (num_possible_cpus() > 1)
0245 dws->max_mem_freq = 10000000U;
0246 else
0247 dws->max_mem_freq = 20000000U;
0248
0249 return 0;
0250 }
0251
0252 static int dw_spi_bt1_probe(struct platform_device *pdev)
0253 {
0254 dw_spi_bt1_init_cb init_func;
0255 struct dw_spi_bt1 *dwsbt1;
0256 struct resource *mem;
0257 struct dw_spi *dws;
0258 int ret;
0259
0260 dwsbt1 = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_bt1), GFP_KERNEL);
0261 if (!dwsbt1)
0262 return -ENOMEM;
0263
0264 dws = &dwsbt1->dws;
0265
0266 dws->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
0267 if (IS_ERR(dws->regs))
0268 return PTR_ERR(dws->regs);
0269
0270 dws->paddr = mem->start;
0271
0272 dwsbt1->clk = devm_clk_get(&pdev->dev, NULL);
0273 if (IS_ERR(dwsbt1->clk))
0274 return PTR_ERR(dwsbt1->clk);
0275
0276 ret = clk_prepare_enable(dwsbt1->clk);
0277 if (ret)
0278 return ret;
0279
0280 dws->bus_num = pdev->id;
0281 dws->reg_io_width = 4;
0282 dws->max_freq = clk_get_rate(dwsbt1->clk);
0283 if (!dws->max_freq) {
0284 ret = -EINVAL;
0285 goto err_disable_clk;
0286 }
0287
0288 init_func = device_get_match_data(&pdev->dev);
0289 ret = init_func(pdev, dwsbt1);
0290 if (ret)
0291 goto err_disable_clk;
0292
0293 pm_runtime_enable(&pdev->dev);
0294
0295 ret = dw_spi_add_host(&pdev->dev, dws);
0296 if (ret)
0297 goto err_disable_clk;
0298
0299 platform_set_drvdata(pdev, dwsbt1);
0300
0301 return 0;
0302
0303 err_disable_clk:
0304 clk_disable_unprepare(dwsbt1->clk);
0305
0306 return ret;
0307 }
0308
0309 static int dw_spi_bt1_remove(struct platform_device *pdev)
0310 {
0311 struct dw_spi_bt1 *dwsbt1 = platform_get_drvdata(pdev);
0312
0313 dw_spi_remove_host(&dwsbt1->dws);
0314
0315 pm_runtime_disable(&pdev->dev);
0316
0317 clk_disable_unprepare(dwsbt1->clk);
0318
0319 return 0;
0320 }
0321
0322 static const struct of_device_id dw_spi_bt1_of_match[] = {
0323 { .compatible = "baikal,bt1-ssi", .data = dw_spi_bt1_std_init},
0324 { .compatible = "baikal,bt1-sys-ssi", .data = dw_spi_bt1_sys_init},
0325 { }
0326 };
0327 MODULE_DEVICE_TABLE(of, dw_spi_bt1_of_match);
0328
0329 static struct platform_driver dw_spi_bt1_driver = {
0330 .probe = dw_spi_bt1_probe,
0331 .remove = dw_spi_bt1_remove,
0332 .driver = {
0333 .name = "bt1-sys-ssi",
0334 .of_match_table = dw_spi_bt1_of_match,
0335 },
0336 };
0337 module_platform_driver(dw_spi_bt1_driver);
0338
0339 MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
0340 MODULE_DESCRIPTION("Baikal-T1 System Boot SPI Controller driver");
0341 MODULE_LICENSE("GPL v2");
0342 MODULE_IMPORT_NS(SPI_DW_CORE);