in spi-bcm63xx-hsspi.c [330:461]
static int bcm63xx_hsspi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct bcm63xx_hsspi *bs;
void __iomem *regs;
struct device *dev = &pdev->dev;
struct clk *clk, *pll_clk = NULL;
int irq, ret;
u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS;
struct reset_control *reset;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return PTR_ERR(regs);
clk = devm_clk_get(dev, "hsspi");
if (IS_ERR(clk))
return PTR_ERR(clk);
reset = devm_reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(reset))
return PTR_ERR(reset);
ret = clk_prepare_enable(clk);
if (ret)
return ret;
ret = reset_control_reset(reset);
if (ret) {
dev_err(dev, "unable to reset device: %d\n", ret);
goto out_disable_clk;
}
rate = clk_get_rate(clk);
if (!rate) {
pll_clk = devm_clk_get(dev, "pll");
if (IS_ERR(pll_clk)) {
ret = PTR_ERR(pll_clk);
goto out_disable_clk;
}
ret = clk_prepare_enable(pll_clk);
if (ret)
goto out_disable_clk;
rate = clk_get_rate(pll_clk);
if (!rate) {
ret = -EINVAL;
goto out_disable_pll_clk;
}
}
master = spi_alloc_master(&pdev->dev, sizeof(*bs));
if (!master) {
ret = -ENOMEM;
goto out_disable_pll_clk;
}
bs = spi_master_get_devdata(master);
bs->pdev = pdev;
bs->clk = clk;
bs->pll_clk = pll_clk;
bs->regs = regs;
bs->speed_hz = rate;
bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
mutex_init(&bs->bus_mutex);
init_completion(&bs->done);
master->dev.of_node = dev->of_node;
if (!dev->of_node)
master->bus_num = HSSPI_BUS_NUM;
of_property_read_u32(dev->of_node, "num-cs", &num_cs);
if (num_cs > 8) {
dev_warn(dev, "unsupported number of cs (%i), reducing to 8\n",
num_cs);
num_cs = HSSPI_SPI_MAX_CS;
}
master->num_chipselect = num_cs;
master->setup = bcm63xx_hsspi_setup;
master->transfer_one_message = bcm63xx_hsspi_transfer_one;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
SPI_RX_DUAL | SPI_TX_DUAL;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->auto_runtime_pm = true;
platform_set_drvdata(pdev, master);
/* Initialize the hardware */
__raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
/* clean up any pending interrupts */
__raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
/* read out default CS polarities */
reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
bs->cs_polarity = reg & GLOBAL_CTRL_CS_POLARITY_MASK;
__raw_writel(reg | GLOBAL_CTRL_CLK_GATE_SSOFF,
bs->regs + HSSPI_GLOBAL_CTRL_REG);
ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
pdev->name, bs);
if (ret)
goto out_put_master;
pm_runtime_enable(&pdev->dev);
/* register and we are done */
ret = devm_spi_register_master(dev, master);
if (ret)
goto out_pm_disable;
return 0;
out_pm_disable:
pm_runtime_disable(&pdev->dev);
out_put_master:
spi_master_put(master);
out_disable_pll_clk:
clk_disable_unprepare(pll_clk);
out_disable_clk:
clk_disable_unprepare(clk);
return ret;
}