Merge tag 'spi-fix-v6.18-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "A moderately large collection of device specific changes here, mostly fixes but also including a few new quirks and device IDs. This is all fairly routine even for the affected devices" * tag 'spi-fix-v6.18-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: dt-bindings: spi-rockchip: Add RK3506 compatible spi: intel-pci: Add support for Intel Wildcat Lake SPI serial flash spi: intel-pci: Add support for Arrow Lake-H SPI serial flash spi: intel: Add support for 128M component density spi: airoha: fix reading/writing of flashes with more than one plane per lun spi: airoha: switch back to non-dma mode in the case of error spi: airoha: add support of dual/quad wires spi modes to exec_op() handler spi: airoha: return an error for continuous mode dirmap creation cases spi: amlogic: fix spifc build error spi: cadence-quadspi: Fix pm_runtime unbalance on dma EPROBE_DEFER spi: spi-nxp-fspi: limit the clock rate for different sample clock source selection spi: spi-nxp-fspi: add extra delay after dll locked spi: spi-nxp-fspi: re-config the clock rate when operation require new clock rate spi: dw-mmio: add error handling for reset_control_deassert() spi: rockchip-sfc: Fix DMA-API usage spi: dt-bindings: cadence: add soc-specific compatible strings for zynqmp and versal-net
This commit is contained in:
@@ -14,9 +14,14 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- cdns,spi-r1p6
|
||||
- xlnx,zynq-spi-r1p6
|
||||
oneOf:
|
||||
- enum:
|
||||
- xlnx,zynq-spi-r1p6
|
||||
- items:
|
||||
- enum:
|
||||
- xlnx,zynqmp-spi-r1p6
|
||||
- xlnx,versal-net-spi-r1p6
|
||||
- const: cdns,spi-r1p6
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -34,6 +34,7 @@ properties:
|
||||
- rockchip,rk3328-spi
|
||||
- rockchip,rk3368-spi
|
||||
- rockchip,rk3399-spi
|
||||
- rockchip,rk3506-spi
|
||||
- rockchip,rk3528-spi
|
||||
- rockchip,rk3562-spi
|
||||
- rockchip,rk3568-spi
|
||||
|
||||
@@ -192,6 +192,14 @@
|
||||
#define SPI_NAND_OP_RESET 0xff
|
||||
#define SPI_NAND_OP_DIE_SELECT 0xc2
|
||||
|
||||
/* SNAND FIFO commands */
|
||||
#define SNAND_FIFO_TX_BUSWIDTH_SINGLE 0x08
|
||||
#define SNAND_FIFO_TX_BUSWIDTH_DUAL 0x09
|
||||
#define SNAND_FIFO_TX_BUSWIDTH_QUAD 0x0a
|
||||
#define SNAND_FIFO_RX_BUSWIDTH_SINGLE 0x0c
|
||||
#define SNAND_FIFO_RX_BUSWIDTH_DUAL 0x0e
|
||||
#define SNAND_FIFO_RX_BUSWIDTH_QUAD 0x0f
|
||||
|
||||
#define SPI_NAND_CACHE_SIZE (SZ_4K + SZ_256)
|
||||
#define SPI_MAX_TRANSFER_SIZE 511
|
||||
|
||||
@@ -387,10 +395,26 @@ static int airoha_snand_set_mode(struct airoha_snand_ctrl *as_ctrl,
|
||||
return regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0);
|
||||
}
|
||||
|
||||
static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
|
||||
const u8 *data, int len)
|
||||
static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl,
|
||||
const u8 *data, int len, int buswidth)
|
||||
{
|
||||
int i, data_len;
|
||||
u8 cmd;
|
||||
|
||||
switch (buswidth) {
|
||||
case 0:
|
||||
case 1:
|
||||
cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE;
|
||||
break;
|
||||
case 2:
|
||||
cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL;
|
||||
break;
|
||||
case 4:
|
||||
cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i += data_len) {
|
||||
int err;
|
||||
@@ -409,16 +433,32 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
|
||||
int len)
|
||||
static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl,
|
||||
u8 *data, int len, int buswidth)
|
||||
{
|
||||
int i, data_len;
|
||||
u8 cmd;
|
||||
|
||||
switch (buswidth) {
|
||||
case 0:
|
||||
case 1:
|
||||
cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE;
|
||||
break;
|
||||
case 2:
|
||||
cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL;
|
||||
break;
|
||||
case 4:
|
||||
cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i += data_len) {
|
||||
int err;
|
||||
|
||||
data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
|
||||
err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
|
||||
err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -618,6 +658,10 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
||||
if (desc->info.offset + desc->info.length > U32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
/* continuous reading is not supported */
|
||||
if (desc->info.length > SPI_NAND_CACHE_SIZE)
|
||||
return -E2BIG;
|
||||
|
||||
if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -654,13 +698,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
|
||||
err = airoha_snand_nfi_config(as_ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_mode_off;
|
||||
|
||||
dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
err = dma_mapping_error(as_ctrl->dev, dma_addr);
|
||||
if (err)
|
||||
return err;
|
||||
goto error_dma_mode_off;
|
||||
|
||||
/* set dma addr */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
|
||||
@@ -689,8 +733,9 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
if (err)
|
||||
goto error_dma_unmap;
|
||||
|
||||
/* set read addr */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);
|
||||
/* set read addr: zero page offset + descriptor read offset */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3,
|
||||
desc->info.offset);
|
||||
if (err)
|
||||
goto error_dma_unmap;
|
||||
|
||||
@@ -760,6 +805,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
error_dma_unmap:
|
||||
dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
error_dma_mode_off:
|
||||
airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -824,7 +871,9 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
if (err)
|
||||
goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);
|
||||
/* set write addr: zero page offset + descriptor write offset */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2,
|
||||
desc->info.offset);
|
||||
if (err)
|
||||
goto error_dma_unmap;
|
||||
|
||||
@@ -892,18 +941,35 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
error_dma_unmap:
|
||||
dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
DMA_TO_DEVICE);
|
||||
airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int airoha_snand_exec_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
u8 data[8], cmd, opcode = op->cmd.opcode;
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
int op_len, addr_len, dummy_len;
|
||||
u8 buf[20], *data;
|
||||
int i, err;
|
||||
|
||||
as_ctrl = spi_controller_get_devdata(mem->spi->controller);
|
||||
|
||||
op_len = op->cmd.nbytes;
|
||||
addr_len = op->addr.nbytes;
|
||||
dummy_len = op->dummy.nbytes;
|
||||
|
||||
if (op_len + dummy_len + addr_len > sizeof(buf))
|
||||
return -EIO;
|
||||
|
||||
data = buf;
|
||||
for (i = 0; i < op_len; i++)
|
||||
*data++ = op->cmd.opcode >> (8 * (op_len - i - 1));
|
||||
for (i = 0; i < addr_len; i++)
|
||||
*data++ = op->addr.val >> (8 * (addr_len - i - 1));
|
||||
for (i = 0; i < dummy_len; i++)
|
||||
*data++ = 0xff;
|
||||
|
||||
/* switch to manual mode */
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
if (err < 0)
|
||||
@@ -914,40 +980,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem,
|
||||
return err;
|
||||
|
||||
/* opcode */
|
||||
err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode));
|
||||
data = buf;
|
||||
err = airoha_snand_write_data(as_ctrl, data, op_len,
|
||||
op->cmd.buswidth);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* addr part */
|
||||
cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8;
|
||||
put_unaligned_be64(op->addr.val, data);
|
||||
|
||||
for (i = ARRAY_SIZE(data) - op->addr.nbytes;
|
||||
i < ARRAY_SIZE(data); i++) {
|
||||
err = airoha_snand_write_data(as_ctrl, cmd, &data[i],
|
||||
sizeof(data[0]));
|
||||
data += op_len;
|
||||
if (addr_len) {
|
||||
err = airoha_snand_write_data(as_ctrl, data, addr_len,
|
||||
op->addr.buswidth);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* dummy */
|
||||
data[0] = 0xff;
|
||||
for (i = 0; i < op->dummy.nbytes; i++) {
|
||||
err = airoha_snand_write_data(as_ctrl, 0x8, &data[0],
|
||||
sizeof(data[0]));
|
||||
data += addr_len;
|
||||
if (dummy_len) {
|
||||
err = airoha_snand_write_data(as_ctrl, data, dummy_len,
|
||||
op->dummy.buswidth);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* data */
|
||||
if (op->data.dir == SPI_MEM_DATA_IN) {
|
||||
err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
|
||||
op->data.nbytes);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out,
|
||||
op->data.nbytes);
|
||||
if (op->data.nbytes) {
|
||||
if (op->data.dir == SPI_MEM_DATA_IN)
|
||||
err = airoha_snand_read_data(as_ctrl, op->data.buf.in,
|
||||
op->data.nbytes,
|
||||
op->data.buswidth);
|
||||
else
|
||||
err = airoha_snand_write_data(as_ctrl, op->data.buf.out,
|
||||
op->data.nbytes,
|
||||
op->data.buswidth);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ static int aml_sfc_set_bus_width(struct aml_sfc *sfc, u8 buswidth, u32 mask)
|
||||
|
||||
for (i = 0; i <= LANE_MAX; i++) {
|
||||
if (buswidth == 1 << i) {
|
||||
conf = i << __bf_shf(mask);
|
||||
conf = i << __ffs(mask);
|
||||
return regmap_update_bits(sfc->regmap_base, SFC_SPI_CFG,
|
||||
mask, conf);
|
||||
}
|
||||
@@ -566,7 +566,7 @@ static int aml_sfc_raw_io_op(struct aml_sfc *sfc, const struct spi_mem_op *op)
|
||||
if (!op->data.nbytes)
|
||||
goto end_xfer;
|
||||
|
||||
conf = (op->data.nbytes >> RAW_SIZE_BW) << __bf_shf(RAW_EXT_SIZE);
|
||||
conf = (op->data.nbytes >> RAW_SIZE_BW) << __ffs(RAW_EXT_SIZE);
|
||||
ret = regmap_update_bits(sfc->regmap_base, SFC_SPI_CFG, RAW_EXT_SIZE, conf);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
@@ -1995,7 +1995,7 @@ static int cqspi_probe(struct platform_device *pdev)
|
||||
if (cqspi->use_direct_mode) {
|
||||
ret = cqspi_request_mmap_dma(cqspi);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto probe_setup_failed;
|
||||
goto probe_dma_failed;
|
||||
}
|
||||
|
||||
if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) {
|
||||
@@ -2019,9 +2019,10 @@ static int cqspi_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
probe_setup_failed:
|
||||
cqspi_controller_enable(cqspi, 0);
|
||||
if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM)))
|
||||
pm_runtime_disable(dev);
|
||||
probe_dma_failed:
|
||||
cqspi_controller_enable(cqspi, 0);
|
||||
probe_reset_failed:
|
||||
if (cqspi->is_jh7110)
|
||||
cqspi_jh7110_disable_clk(pdev, cqspi);
|
||||
|
||||
@@ -358,7 +358,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(dwsmmio->rstc))
|
||||
return PTR_ERR(dwsmmio->rstc);
|
||||
|
||||
reset_control_deassert(dwsmmio->rstc);
|
||||
ret = reset_control_deassert(dwsmmio->rstc);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "Failed to deassert resets\n");
|
||||
|
||||
dws->bus_num = pdev->id;
|
||||
|
||||
|
||||
@@ -75,10 +75,12 @@ static const struct pci_device_id intel_spi_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x38a4), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4d23), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x51a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x54a4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x5794), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7723), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7a24), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info },
|
||||
{ PCI_VDEVICE(INTEL, 0x7e23), (unsigned long)&cnl_info },
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
#define FLCOMP_C0DEN_16M 0x05
|
||||
#define FLCOMP_C0DEN_32M 0x06
|
||||
#define FLCOMP_C0DEN_64M 0x07
|
||||
#define FLCOMP_C0DEN_128M 0x08
|
||||
|
||||
#define INTEL_SPI_TIMEOUT 5000 /* ms */
|
||||
#define INTEL_SPI_FIFO_SZ 64
|
||||
@@ -1347,7 +1348,12 @@ static int intel_spi_read_desc(struct intel_spi *ispi)
|
||||
case FLCOMP_C0DEN_64M:
|
||||
ispi->chip0_size = SZ_64M;
|
||||
break;
|
||||
case FLCOMP_C0DEN_128M:
|
||||
ispi->chip0_size = SZ_128M;
|
||||
break;
|
||||
default:
|
||||
dev_warn(ispi->dev, "unsupported C0DEN: %#lx\n",
|
||||
flcomp & FLCOMP_C0DEN_MASK);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -404,6 +404,10 @@ struct nxp_fspi {
|
||||
#define FSPI_NEED_INIT BIT(0)
|
||||
#define FSPI_DTR_MODE BIT(1)
|
||||
int flags;
|
||||
/* save the previous operation clock rate */
|
||||
unsigned long pre_op_rate;
|
||||
/* the max clock rate fspi output to device */
|
||||
unsigned long max_rate;
|
||||
};
|
||||
|
||||
static inline int needs_ip_only(struct nxp_fspi *f)
|
||||
@@ -685,10 +689,13 @@ static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
|
||||
* change the mode back to mode 0.
|
||||
*/
|
||||
reg = fspi_readl(f, f->iobase + FSPI_MCR0);
|
||||
if (op_is_dtr)
|
||||
if (op_is_dtr) {
|
||||
reg |= FSPI_MCR0_RXCLKSRC(3);
|
||||
else /*select mode 0 */
|
||||
f->max_rate = 166000000;
|
||||
} else { /*select mode 0 */
|
||||
reg &= ~FSPI_MCR0_RXCLKSRC(3);
|
||||
f->max_rate = 66000000;
|
||||
}
|
||||
fspi_writel(f, reg, f->iobase + FSPI_MCR0);
|
||||
}
|
||||
|
||||
@@ -719,6 +726,12 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
|
||||
0, POLL_TOUT, true);
|
||||
if (ret)
|
||||
dev_warn(f->dev, "DLL lock failed, please fix it!\n");
|
||||
|
||||
/*
|
||||
* For ERR050272, DLL lock status bit is not accurate,
|
||||
* wait for 4us more as a workaround.
|
||||
*/
|
||||
udelay(4);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -780,11 +793,17 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
|
||||
uint64_t size_kb;
|
||||
|
||||
/*
|
||||
* Return, if previously selected target device is same as current
|
||||
* requested target device. Also the DTR or STR mode do not change.
|
||||
* Return when following condition all meet,
|
||||
* 1, if previously selected target device is same as current
|
||||
* requested target device.
|
||||
* 2, the DTR or STR mode do not change.
|
||||
* 3, previous operation max rate equals current one.
|
||||
*
|
||||
* For other case, need to re-config.
|
||||
*/
|
||||
if ((f->selected == spi_get_chipselect(spi, 0)) &&
|
||||
(!!(f->flags & FSPI_DTR_MODE) == op_is_dtr))
|
||||
(!!(f->flags & FSPI_DTR_MODE) == op_is_dtr) &&
|
||||
(f->pre_op_rate == op->max_freq))
|
||||
return;
|
||||
|
||||
/* Reset FLSHxxCR0 registers */
|
||||
@@ -802,6 +821,7 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
|
||||
dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0));
|
||||
|
||||
nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr);
|
||||
rate = min(f->max_rate, op->max_freq);
|
||||
|
||||
if (op_is_dtr) {
|
||||
f->flags |= FSPI_DTR_MODE;
|
||||
@@ -832,6 +852,8 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
|
||||
else
|
||||
nxp_fspi_dll_override(f);
|
||||
|
||||
f->pre_op_rate = op->max_freq;
|
||||
|
||||
f->selected = spi_get_chipselect(spi, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -704,7 +704,12 @@ static int rockchip_sfc_probe(struct platform_device *pdev)
|
||||
ret = -ENOMEM;
|
||||
goto err_dma;
|
||||
}
|
||||
sfc->dma_buffer = virt_to_phys(sfc->buffer);
|
||||
sfc->dma_buffer = dma_map_single(dev, sfc->buffer,
|
||||
sfc->max_iosize, DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(dev, sfc->dma_buffer)) {
|
||||
ret = -ENOMEM;
|
||||
goto err_dma_map;
|
||||
}
|
||||
}
|
||||
|
||||
ret = devm_spi_register_controller(dev, host);
|
||||
@@ -715,6 +720,9 @@ static int rockchip_sfc_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
err_register:
|
||||
dma_unmap_single(dev, sfc->dma_buffer, sfc->max_iosize,
|
||||
DMA_BIDIRECTIONAL);
|
||||
err_dma_map:
|
||||
free_pages((unsigned long)sfc->buffer, get_order(sfc->max_iosize));
|
||||
err_dma:
|
||||
pm_runtime_get_sync(dev);
|
||||
@@ -736,6 +744,8 @@ static void rockchip_sfc_remove(struct platform_device *pdev)
|
||||
struct spi_controller *host = sfc->host;
|
||||
|
||||
spi_unregister_controller(host);
|
||||
dma_unmap_single(&pdev->dev, sfc->dma_buffer, sfc->max_iosize,
|
||||
DMA_BIDIRECTIONAL);
|
||||
free_pages((unsigned long)sfc->buffer, get_order(sfc->max_iosize));
|
||||
|
||||
clk_disable_unprepare(sfc->clk);
|
||||
|
||||
Reference in New Issue
Block a user