提交 c26211d3 编写于 作者: B Brian Norris

mtd: brcmnand: add extra SoC support to library

There are a few small hooks required for chips like BCM63138 and the
iProc family. Let's introduce those now.
Signed-off-by: NBrian Norris <computersforpeace@gmail.com>
Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
Tested-by: NFlorian Fainelli <f.fainelli@gmail.com>
上级 3a52be8a
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -119,6 +119,9 @@ struct brcmnand_controller {
unsigned int dma_irq;
int nand_version;
/* Some SoCs provide custom interrupt status register(s) */
struct brcmnand_soc *soc;
int cmd_pending;
bool dma_pending;
struct completion done;
......@@ -965,6 +968,17 @@ static irqreturn_t brcmnand_ctlrdy_irq(int irq, void *data)
return IRQ_HANDLED;
}
/* Handle SoC-specific interrupt hardware */
static irqreturn_t brcmnand_irq(int irq, void *data)
{
struct brcmnand_controller *ctrl = data;
if (ctrl->soc->ctlrdy_ack(ctrl->soc))
return brcmnand_ctlrdy_irq(irq, data);
return IRQ_NONE;
}
static irqreturn_t brcmnand_dma_irq(int irq, void *data)
{
struct brcmnand_controller *ctrl = data;
......@@ -1153,12 +1167,18 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
if (native_cmd == CMD_PARAMETER_READ ||
native_cmd == CMD_PARAMETER_CHANGE_COL) {
int i;
brcmnand_soc_data_bus_prepare(ctrl->soc);
/*
* Must cache the FLASH_CACHE now, since changes in
* SECTOR_SIZE_1K may invalidate it
*/
for (i = 0; i < FC_WORDS; i++)
ctrl->flash_cache[i] = brcmnand_read_fc(ctrl, i);
brcmnand_soc_data_bus_unprepare(ctrl->soc);
/* Cleanup from HW quirk: restore SECTOR_SIZE_1K */
if (host->hwcfg.sector_size_1k)
brcmnand_set_sector_size_1k(host,
......@@ -1371,10 +1391,15 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
brcmnand_send_cmd(host, CMD_PAGE_READ);
brcmnand_waitfunc(mtd, chip);
if (likely(buf))
if (likely(buf)) {
brcmnand_soc_data_bus_prepare(ctrl->soc);
for (j = 0; j < FC_WORDS; j++, buf++)
*buf = brcmnand_read_fc(ctrl, j);
brcmnand_soc_data_bus_unprepare(ctrl->soc);
}
if (oob)
oob += read_oob_from_regs(ctrl, i, oob,
mtd->oobsize / trans,
......@@ -1546,12 +1571,17 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip,
lower_32_bits(addr));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
if (buf)
if (buf) {
brcmnand_soc_data_bus_prepare(ctrl->soc);
for (j = 0; j < FC_WORDS; j++, buf++)
brcmnand_write_fc(ctrl, j, *buf);
else if (oob)
brcmnand_soc_data_bus_unprepare(ctrl->soc);
} else if (oob) {
for (j = 0; j < FC_WORDS; j++)
brcmnand_write_fc(ctrl, j, 0xffffffff);
}
if (oob) {
oob += write_oob_to_regs(ctrl, i, oob,
......@@ -1995,6 +2025,11 @@ static int brcmnand_resume(struct device *dev)
brcmnand_write_reg(ctrl, BRCMNAND_CS_XOR, ctrl->nand_cs_nand_xor);
brcmnand_write_reg(ctrl, BRCMNAND_CORR_THRESHOLD,
ctrl->corr_stat_threshold);
if (ctrl->soc) {
/* Clear/re-enable interrupt */
ctrl->soc->ctlrdy_ack(ctrl->soc);
ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true);
}
list_for_each_entry(host, &ctrl->host_list, node) {
struct mtd_info *mtd = &host->mtd;
......@@ -2139,8 +2174,24 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
return -ENODEV;
}
ret = devm_request_irq(dev, ctrl->irq, brcmnand_ctlrdy_irq, 0,
DRV_NAME, ctrl);
/*
* Some SoCs integrate this controller (e.g., its interrupt bits) in
* interesting ways
*/
if (soc) {
ctrl->soc = soc;
ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0,
DRV_NAME, ctrl);
/* Enable interrupt */
ctrl->soc->ctlrdy_ack(ctrl->soc);
ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true);
} else {
/* Use standard interrupt infrastructure */
ret = devm_request_irq(dev, ctrl->irq, brcmnand_ctlrdy_irq, 0,
DRV_NAME, ctrl);
}
if (ret < 0) {
dev_err(dev, "can't allocate IRQ %d: error %d\n",
ctrl->irq, ret);
......
......@@ -23,8 +23,23 @@ struct dev_pm_ops;
struct brcmnand_soc {
struct platform_device *pdev;
void *priv;
bool (*ctlrdy_ack)(struct brcmnand_soc *soc);
void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en);
void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare);
};
static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc)
{
if (soc && soc->prepare_data_bus)
soc->prepare_data_bus(soc, true);
}
static inline void brcmnand_soc_data_bus_unprepare(struct brcmnand_soc *soc)
{
if (soc && soc->prepare_data_bus)
soc->prepare_data_bus(soc, false);
}
static inline u32 brcmnand_readl(void __iomem *addr)
{
/*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部