X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fspi%2Fkirkwood_spi.c;h=caa91e3e81718c8c4626fbb819a121f14e28e3e8;hb=277f037074fbb73be10a7bff27079b6eb0a3bfbb;hp=dfe542db64ef8371532af52029e4770dd9d04172;hpb=87a5d601031652293ec4b729fdb7ee01bbd940a8;p=u-boot diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c index dfe542db64..caa91e3e81 100644 --- a/drivers/spi/kirkwood_spi.c +++ b/drivers/spi/kirkwood_spi.c @@ -34,65 +34,105 @@ static struct kwspi_registers *spireg = (struct kwspi_registers *)KW_SPI_BASE; +u32 cs_spi_mpp_back[2]; + struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { struct spi_slave *slave; u32 data; - u32 kwspi_mpp_config[] = { - MPP0_GPIO, - MPP7_SPI_SCn, - 0 + static const u32 kwspi_mpp_config[2][2] = { + { MPP0_SPI_SCn, 0 }, /* if cs == 0 */ + { MPP7_SPI_SCn, 0 } /* if cs != 0 */ }; if (!spi_cs_is_valid(bus, cs)) return NULL; - slave = malloc(sizeof(struct spi_slave)); + slave = spi_alloc_slave_base(bus, cs); if (!slave) return NULL; - slave->bus = bus; - slave->cs = cs; - writel(~KWSPI_CSN_ACT | KWSPI_SMEMRDY, &spireg->ctrl); /* calculate spi clock prescaller using max_hz */ - data = ((CONFIG_SYS_TCLK / 2) / max_hz) & KWSPI_CLKPRESCL_MASK; - data |= 0x10; + data = ((CONFIG_SYS_TCLK / 2) / max_hz) + 0x10; + data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data; + data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data; /* program spi clock prescaller using max_hz */ writel(KWSPI_ADRLEN_3BYTE | data, &spireg->cfg); debug("data = 0x%08x \n", data); writel(KWSPI_SMEMRDIRQ, &spireg->irq_cause); - writel(KWSPI_IRQMASK, spireg->irq_mask); + writel(KWSPI_IRQMASK, &spireg->irq_mask); /* program mpp registers to select SPI_CSn */ - if (cs) { - kwspi_mpp_config[0] = MPP0_GPIO; - kwspi_mpp_config[1] = MPP7_SPI_SCn; - } else { - kwspi_mpp_config[0] = MPP0_SPI_SCn; - kwspi_mpp_config[1] = MPP7_GPO; - } - kirkwood_mpp_conf(kwspi_mpp_config); + kirkwood_mpp_conf(kwspi_mpp_config[cs ? 1 : 0], cs_spi_mpp_back); return slave; } void spi_free_slave(struct spi_slave *slave) { + kirkwood_mpp_conf(cs_spi_mpp_back, NULL); free(slave); } -int spi_claim_bus(struct spi_slave *slave) +#if defined(CONFIG_SYS_KW_SPI_MPP) +u32 spi_mpp_backup[4]; +#endif + +__attribute__((weak)) int board_spi_claim_bus(struct spi_slave *slave) { return 0; } +int spi_claim_bus(struct spi_slave *slave) +{ +#if defined(CONFIG_SYS_KW_SPI_MPP) + u32 config; + u32 spi_mpp_config[4]; + + config = CONFIG_SYS_KW_SPI_MPP; + + if (config & MOSI_MPP6) + spi_mpp_config[0] = MPP6_SPI_MOSI; + else + spi_mpp_config[0] = MPP1_SPI_MOSI; + + if (config & SCK_MPP10) + spi_mpp_config[1] = MPP10_SPI_SCK; + else + spi_mpp_config[1] = MPP2_SPI_SCK; + + if (config & MISO_MPP11) + spi_mpp_config[2] = MPP11_SPI_MISO; + else + spi_mpp_config[2] = MPP3_SPI_MISO; + + spi_mpp_config[3] = 0; + spi_mpp_backup[3] = 0; + + /* set new spi mpp and save current mpp config */ + kirkwood_mpp_conf(spi_mpp_config, spi_mpp_backup); + +#endif + + return board_spi_claim_bus(slave); +} + +__attribute__((weak)) void board_spi_release_bus(struct spi_slave *slave) +{ +} + void spi_release_bus(struct spi_slave *slave) { +#if defined(CONFIG_SYS_KW_SPI_MPP) + kirkwood_mpp_conf(spi_mpp_backup, NULL); +#endif + + board_spi_release_bus(slave); } #ifndef CONFIG_SPI_CS_IS_VALID