Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: sh-hspi: control spi clock more correctly

Current sh-hspi had used platform-specific speed.
This patch remove it, and use spi_transfer specific speed.
It removes unnecessary flags from struct sh_hspi_info,
but struct sh_hspi_info is still exist, since sh-hspi needs
platform info in the future.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>

authored by

Kuninori Morimoto and committed by
Grant Likely
49e599b8 ec139b67

+70 -27
+70 -16
drivers/spi/spi-sh-hspi.c
··· 22 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 23 * 24 24 */ 25 + 26 + #include <linux/clk.h> 25 27 #include <linux/module.h> 26 28 #include <linux/kernel.h> 27 29 #include <linux/timer.h> ··· 52 50 void __iomem *addr; 53 51 struct spi_master *master; 54 52 struct device *dev; 53 + struct clk *clk; 55 54 }; 56 55 57 56 /* ··· 165 162 return 0; 166 163 } 167 164 165 + static void hspi_hw_setup(struct hspi_priv *hspi, 166 + struct spi_message *msg, 167 + struct spi_transfer *t) 168 + { 169 + struct spi_device *spi = msg->spi; 170 + struct device *dev = hspi->dev; 171 + u32 target_rate; 172 + u32 spcr, idiv_clk; 173 + u32 rate, best_rate, min, tmp; 174 + 175 + target_rate = t ? t->speed_hz : 0; 176 + if (!target_rate) 177 + target_rate = spi->max_speed_hz; 178 + 179 + /* 180 + * find best IDIV/CLKCx settings 181 + */ 182 + min = ~0; 183 + best_rate = 0; 184 + spcr = 0; 185 + for (idiv_clk = 0x00; idiv_clk <= 0x3F; idiv_clk++) { 186 + rate = clk_get_rate(hspi->clk); 187 + 188 + /* IDIV calculation */ 189 + if (idiv_clk & (1 << 5)) 190 + rate /= 128; 191 + else 192 + rate /= 16; 193 + 194 + /* CLKCx calculation */ 195 + rate /= (((idiv_clk & 0x1F) + 1) * 2) ; 196 + 197 + /* save best settings */ 198 + tmp = abs(target_rate - rate); 199 + if (tmp < min) { 200 + min = tmp; 201 + spcr = idiv_clk; 202 + best_rate = rate; 203 + } 204 + } 205 + 206 + if (spi->mode & SPI_CPHA) 207 + spcr |= 1 << 7; 208 + if (spi->mode & SPI_CPOL) 209 + spcr |= 1 << 6; 210 + 211 + dev_dbg(dev, "speed %d/%d\n", target_rate, best_rate); 212 + 213 + hspi_write(hspi, SPCR, spcr); 214 + hspi_write(hspi, SPSR, 0x0); 215 + hspi_write(hspi, SPSCR, 0x1); /* master mode */ 216 + } 217 + 168 218 static int hspi_transfer_one_message(struct spi_master *master, 169 219 struct spi_message *msg) 170 220 { ··· 229 173 230 174 ret = 0; 231 175 list_for_each_entry(t, &msg->transfers, transfer_list) { 176 + hspi_hw_setup(hspi, msg, t); 177 + 232 178 if (t->tx_buf) { 233 179 ret = hspi_push(hspi, msg, t); 234 180 if (ret < 0) ··· 255 197 { 256 198 struct hspi_priv *hspi = spi_master_get_devdata(spi->master); 257 199 struct device *dev = hspi->dev; 258 - struct sh_hspi_info *info = hspi2info(hspi); 259 - u32 data; 260 200 261 201 if (8 != spi->bits_per_word) { 262 202 dev_err(dev, "bits_per_word should be 8\n"); 263 203 return -EIO; 264 204 } 265 - 266 - /* setup first of all in under pm_runtime */ 267 - data = SH_HSPI_CLK_DIVC(info->flags); 268 - 269 - if (info->flags & SH_HSPI_FBS) 270 - data |= 1 << 7; 271 - if (info->flags & SH_HSPI_CLKP_HIGH) 272 - data |= 1 << 6; 273 - if (info->flags & SH_HSPI_IDIV_DIV128) 274 - data |= 1 << 5; 275 - 276 - hspi_write(hspi, SPCR, data); 277 - hspi_write(hspi, SPSR, 0x0); 278 - hspi_write(hspi, SPSCR, 0x1); /* master mode */ 279 205 280 206 dev_dbg(dev, "%s setup\n", spi->modalias); 281 207 ··· 279 237 struct resource *res; 280 238 struct spi_master *master; 281 239 struct hspi_priv *hspi; 240 + struct clk *clk; 282 241 int ret; 283 242 284 243 /* get base addr */ ··· 295 252 return -ENOMEM; 296 253 } 297 254 255 + clk = clk_get(NULL, "shyway_clk"); 256 + if (!clk) { 257 + dev_err(&pdev->dev, "shyway_clk is required\n"); 258 + ret = -EINVAL; 259 + goto error0; 260 + } 261 + 298 262 hspi = spi_master_get_devdata(master); 299 263 dev_set_drvdata(&pdev->dev, hspi); 300 264 301 265 /* init hspi */ 302 266 hspi->master = master; 303 267 hspi->dev = &pdev->dev; 268 + hspi->clk = clk; 304 269 hspi->addr = devm_ioremap(hspi->dev, 305 270 res->start, resource_size(res)); 306 271 if (!hspi->addr) { ··· 340 289 error2: 341 290 devm_iounmap(hspi->dev, hspi->addr); 342 291 error1: 292 + clk_put(clk); 293 + error0: 343 294 spi_master_put(master); 344 295 345 296 return ret; ··· 353 300 354 301 pm_runtime_disable(&pdev->dev); 355 302 303 + clk_put(hspi->clk); 356 304 spi_unregister_master(hspi->master); 357 305 devm_iounmap(hspi->dev, hspi->addr); 358 306
-11
include/linux/spi/sh_hspi.h
··· 17 17 #ifndef SH_HSPI_H 18 18 #define SH_HSPI_H 19 19 20 - /* 21 - * flags 22 - * 23 - * 24 - */ 25 - #define SH_HSPI_CLK_DIVC(d) (d & 0xFF) 26 - 27 - #define SH_HSPI_FBS (1 << 8) 28 - #define SH_HSPI_CLKP_HIGH (1 << 9) /* default LOW */ 29 - #define SH_HSPI_IDIV_DIV128 (1 << 10) /* default div16 */ 30 20 struct sh_hspi_info { 31 - u32 flags; 32 21 }; 33 22 34 23 #endif