308 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * SuperH HSPI bus driver4 *5 * Copyright (C) 2011 Kuninori Morimoto6 *7 * Based on spi-sh.c:8 * Based on pxa2xx_spi.c:9 * Copyright (C) 2011 Renesas Solutions Corp.10 * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs11 */12 13#include <linux/clk.h>14#include <linux/module.h>15#include <linux/kernel.h>16#include <linux/timer.h>17#include <linux/delay.h>18#include <linux/list.h>19#include <linux/interrupt.h>20#include <linux/platform_device.h>21#include <linux/pm_runtime.h>22#include <linux/io.h>23#include <linux/spi/spi.h>24#include <linux/spi/sh_hspi.h>25 26#define SPCR 0x0027#define SPSR 0x0428#define SPSCR 0x0829#define SPTBR 0x0C30#define SPRBR 0x1031#define SPCR2 0x1432 33/* SPSR */34#define RXFL (1 << 2)35 36struct hspi_priv {37 void __iomem *addr;38 struct spi_controller *ctlr;39 struct device *dev;40 struct clk *clk;41};42 43/*44 * basic function45 */46static void hspi_write(struct hspi_priv *hspi, int reg, u32 val)47{48 iowrite32(val, hspi->addr + reg);49}50 51static u32 hspi_read(struct hspi_priv *hspi, int reg)52{53 return ioread32(hspi->addr + reg);54}55 56static void hspi_bit_set(struct hspi_priv *hspi, int reg, u32 mask, u32 set)57{58 u32 val = hspi_read(hspi, reg);59 60 val &= ~mask;61 val |= set & mask;62 63 hspi_write(hspi, reg, val);64}65 66/*67 * transfer function68 */69static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)70{71 int t = 256;72 73 while (t--) {74 if ((mask & hspi_read(hspi, SPSR)) == val)75 return 0;76 77 udelay(10);78 }79 80 dev_err(hspi->dev, "timeout\n");81 return -ETIMEDOUT;82}83 84/*85 * spi host function86 */87 88#define hspi_hw_cs_enable(hspi) hspi_hw_cs_ctrl(hspi, 0)89#define hspi_hw_cs_disable(hspi) hspi_hw_cs_ctrl(hspi, 1)90static void hspi_hw_cs_ctrl(struct hspi_priv *hspi, int hi)91{92 hspi_bit_set(hspi, SPSCR, (1 << 6), (hi) << 6);93}94 95static void hspi_hw_setup(struct hspi_priv *hspi,96 struct spi_message *msg,97 struct spi_transfer *t)98{99 struct spi_device *spi = msg->spi;100 struct device *dev = hspi->dev;101 u32 spcr, idiv_clk;102 u32 rate, best_rate, min, tmp;103 104 /*105 * find best IDIV/CLKCx settings106 */107 min = ~0;108 best_rate = 0;109 spcr = 0;110 for (idiv_clk = 0x00; idiv_clk <= 0x3F; idiv_clk++) {111 rate = clk_get_rate(hspi->clk);112 113 /* IDIV calculation */114 if (idiv_clk & (1 << 5))115 rate /= 128;116 else117 rate /= 16;118 119 /* CLKCx calculation */120 rate /= (((idiv_clk & 0x1F) + 1) * 2);121 122 /* save best settings */123 tmp = abs(t->speed_hz - rate);124 if (tmp < min) {125 min = tmp;126 spcr = idiv_clk;127 best_rate = rate;128 }129 }130 131 if (spi->mode & SPI_CPHA)132 spcr |= 1 << 7;133 if (spi->mode & SPI_CPOL)134 spcr |= 1 << 6;135 136 dev_dbg(dev, "speed %d/%d\n", t->speed_hz, best_rate);137 138 hspi_write(hspi, SPCR, spcr);139 hspi_write(hspi, SPSR, 0x0);140 hspi_write(hspi, SPSCR, 0x21); /* master mode / CS control */141}142 143static int hspi_transfer_one_message(struct spi_controller *ctlr,144 struct spi_message *msg)145{146 struct hspi_priv *hspi = spi_controller_get_devdata(ctlr);147 struct spi_transfer *t;148 u32 tx;149 u32 rx;150 int ret, i;151 unsigned int cs_change;152 const int nsecs = 50;153 154 dev_dbg(hspi->dev, "%s\n", __func__);155 156 cs_change = 1;157 ret = 0;158 list_for_each_entry(t, &msg->transfers, transfer_list) {159 160 if (cs_change) {161 hspi_hw_setup(hspi, msg, t);162 hspi_hw_cs_enable(hspi);163 ndelay(nsecs);164 }165 cs_change = t->cs_change;166 167 for (i = 0; i < t->len; i++) {168 169 /* wait remains */170 ret = hspi_status_check_timeout(hspi, 0x1, 0);171 if (ret < 0)172 break;173 174 tx = 0;175 if (t->tx_buf)176 tx = (u32)((u8 *)t->tx_buf)[i];177 178 hspi_write(hspi, SPTBR, tx);179 180 /* wait receive */181 ret = hspi_status_check_timeout(hspi, 0x4, 0x4);182 if (ret < 0)183 break;184 185 rx = hspi_read(hspi, SPRBR);186 if (t->rx_buf)187 ((u8 *)t->rx_buf)[i] = (u8)rx;188 189 }190 191 msg->actual_length += t->len;192 193 spi_transfer_delay_exec(t);194 195 if (cs_change) {196 ndelay(nsecs);197 hspi_hw_cs_disable(hspi);198 ndelay(nsecs);199 }200 }201 202 msg->status = ret;203 if (!cs_change) {204 ndelay(nsecs);205 hspi_hw_cs_disable(hspi);206 }207 spi_finalize_current_message(ctlr);208 209 return ret;210}211 212static int hspi_probe(struct platform_device *pdev)213{214 struct resource *res;215 struct spi_controller *ctlr;216 struct hspi_priv *hspi;217 struct clk *clk;218 int ret;219 220 /* get base addr */221 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);222 if (!res) {223 dev_err(&pdev->dev, "invalid resource\n");224 return -EINVAL;225 }226 227 ctlr = spi_alloc_host(&pdev->dev, sizeof(*hspi));228 if (!ctlr)229 return -ENOMEM;230 231 clk = clk_get(&pdev->dev, NULL);232 if (IS_ERR(clk)) {233 dev_err(&pdev->dev, "couldn't get clock\n");234 ret = -EINVAL;235 goto error0;236 }237 238 hspi = spi_controller_get_devdata(ctlr);239 platform_set_drvdata(pdev, hspi);240 241 /* init hspi */242 hspi->ctlr = ctlr;243 hspi->dev = &pdev->dev;244 hspi->clk = clk;245 hspi->addr = devm_ioremap(hspi->dev,246 res->start, resource_size(res));247 if (!hspi->addr) {248 ret = -ENOMEM;249 goto error1;250 }251 252 pm_runtime_enable(&pdev->dev);253 254 ctlr->bus_num = pdev->id;255 ctlr->mode_bits = SPI_CPOL | SPI_CPHA;256 ctlr->dev.of_node = pdev->dev.of_node;257 ctlr->auto_runtime_pm = true;258 ctlr->transfer_one_message = hspi_transfer_one_message;259 ctlr->bits_per_word_mask = SPI_BPW_MASK(8);260 261 ret = devm_spi_register_controller(&pdev->dev, ctlr);262 if (ret < 0) {263 dev_err(&pdev->dev, "devm_spi_register_controller error.\n");264 goto error2;265 }266 267 return 0;268 269 error2:270 pm_runtime_disable(&pdev->dev);271 error1:272 clk_put(clk);273 error0:274 spi_controller_put(ctlr);275 276 return ret;277}278 279static void hspi_remove(struct platform_device *pdev)280{281 struct hspi_priv *hspi = platform_get_drvdata(pdev);282 283 pm_runtime_disable(&pdev->dev);284 285 clk_put(hspi->clk);286}287 288static const struct of_device_id hspi_of_match[] = {289 { .compatible = "renesas,hspi", },290 { /* sentinel */ }291};292MODULE_DEVICE_TABLE(of, hspi_of_match);293 294static struct platform_driver hspi_driver = {295 .probe = hspi_probe,296 .remove_new = hspi_remove,297 .driver = {298 .name = "sh-hspi",299 .of_match_table = hspi_of_match,300 },301};302module_platform_driver(hspi_driver);303 304MODULE_DESCRIPTION("SuperH HSPI bus driver");305MODULE_LICENSE("GPL v2");306MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");307MODULE_ALIAS("platform:sh-hspi");308