Lines Matching +full:stacked +full:- +full:memories

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * LPDDR2-NVM MTD driver. This module provides read, write, erase, lock/unlock
4 * support for LPDDR2-NVM PCM memories
54 /* LPDDR2-NVM Commands */
63 /* LPDDR2-NVM Registers offset */
72 * &bus_width: memory bus-width (eg: x16 2 Bytes, x32 4 Bytes)
92 * Build Mode Register Configuration DataMask based on device bus-width
105 * Build Status Register OK DataMask based on device bus-width
123 struct pcm_int_data *pcm_data = map->fldrv_priv; in ow_reg_add()
125 val = map->pfow_base + offset*pcm_data->bus_width; in ow_reg_add()
131 * Enable lpddr2-nvm Overlay Window
132 * Overlay Window is a memory mapped area containing all LPDDR2-NVM registers
138 struct pcm_int_data *pcm_data = map->fldrv_priv; in ow_enable()
140 writel_relaxed(build_mr_cfgmask(pcm_data->bus_width) | 0x18, in ow_enable()
141 pcm_data->ctl_regs + LPDDR2_MODE_REG_CFG); in ow_enable()
142 writel_relaxed(0x01, pcm_data->ctl_regs + LPDDR2_MODE_REG_DATA); in ow_enable()
146 * Disable lpddr2-nvm Overlay Window
147 * Overlay Window is a memory mapped area containing all LPDDR2-NVM registers
153 struct pcm_int_data *pcm_data = map->fldrv_priv; in ow_disable()
155 writel_relaxed(build_mr_cfgmask(pcm_data->bus_width) | 0x18, in ow_disable()
156 pcm_data->ctl_regs + LPDDR2_MODE_REG_CFG); in ow_disable()
157 writel_relaxed(0x02, pcm_data->ctl_regs + LPDDR2_MODE_REG_DATA); in ow_disable()
161 * Execute lpddr2-nvm operations
169 map_word data_h = { {0} }; /* only for 2x x16 devices stacked */ in lpddr2_nvm_do_op()
171 struct pcm_int_data *pcm_data = map->fldrv_priv; in lpddr2_nvm_do_op()
172 u_int sr_ok_datamask = build_sr_ok_datamask(pcm_data->bus_width); in lpddr2_nvm_do_op()
191 if (pcm_data->bus_width == 0x0004) { /* 2x16 devices stacked */ in lpddr2_nvm_do_op()
206 map_write(map, build_map_word(buf[i]), map->pfow_base + in lpddr2_nvm_do_op()
213 if (pcm_data->bus_width == 0x0004) /* 2x16 devices stacked */ in lpddr2_nvm_do_op()
220 if (pcm_data->bus_width == 0x0004) {/* 2x16 devices stacked */ in lpddr2_nvm_do_op()
227 return (((status_reg & sr_ok_datamask) == sr_ok_datamask) ? 0 : -EIO); in lpddr2_nvm_do_op()
231 * Execute lpddr2-nvm operations @ block level
236 struct map_info *map = mtd->priv; in lpddr2_nvm_do_block_op()
251 add += mtd->erasesize; in lpddr2_nvm_do_block_op()
301 struct map_info *map = mtd->priv; in lpddr2_nvm_read()
319 struct map_info *map = mtd->priv; in lpddr2_nvm_write()
320 struct pcm_int_data *pcm_data = map->fldrv_priv; in lpddr2_nvm_write()
335 if (!(IS_ALIGNED(add, mtd->writesize))) { /* do sw program */ in lpddr2_nvm_write()
338 if (pcm_data->bus_width == 0x0004) {/* 2x16 devices */ in lpddr2_nvm_write()
347 add += pcm_data->bus_width; in lpddr2_nvm_write()
348 tot_len += pcm_data->bus_width; in lpddr2_nvm_write()
350 current_len = min(target_len - tot_len, in lpddr2_nvm_write()
351 (u_long) mtd->writesize); in lpddr2_nvm_write()
374 return lpddr2_nvm_do_block_op(mtd, instr->addr, instr->len, in lpddr2_nvm_erase()
418 pcm_data = devm_kzalloc(&pdev->dev, sizeof(*pcm_data), GFP_KERNEL); in lpddr2_nvm_probe()
420 return -ENOMEM; in lpddr2_nvm_probe()
422 pcm_data->bus_width = BUS_WIDTH; in lpddr2_nvm_probe()
425 map = devm_kzalloc(&pdev->dev, sizeof(*map), GFP_KERNEL); in lpddr2_nvm_probe()
427 return -ENOMEM; in lpddr2_nvm_probe()
429 mtd = devm_kzalloc(&pdev->dev, sizeof(*mtd), GFP_KERNEL); in lpddr2_nvm_probe()
431 return -ENOMEM; in lpddr2_nvm_probe()
436 return -ENODEV; in lpddr2_nvm_probe()
440 .virt = devm_ioremap_resource(&pdev->dev, add_range), in lpddr2_nvm_probe()
441 .name = pdev->dev.init_name, in lpddr2_nvm_probe()
442 .phys = add_range->start, in lpddr2_nvm_probe()
444 .bankwidth = pcm_data->bus_width / 2, in lpddr2_nvm_probe()
449 if (IS_ERR(map->virt)) in lpddr2_nvm_probe()
450 return PTR_ERR(map->virt); in lpddr2_nvm_probe()
454 pcm_data->ctl_regs = devm_platform_ioremap_resource(pdev, 1); in lpddr2_nvm_probe()
455 if (IS_ERR(pcm_data->ctl_regs)) in lpddr2_nvm_probe()
456 return PTR_ERR(pcm_data->ctl_regs); in lpddr2_nvm_probe()
460 mtd->dev.parent = &pdev->dev; in lpddr2_nvm_probe()
461 mtd->name = pdev->dev.init_name; in lpddr2_nvm_probe()
462 mtd->priv = map; in lpddr2_nvm_probe()
463 mtd->size = resource_size(add_range); in lpddr2_nvm_probe()
464 mtd->erasesize = ERASE_BLOCKSIZE * pcm_data->bus_width; in lpddr2_nvm_probe()
465 mtd->writebufsize = WRITE_BUFFSIZE * pcm_data->bus_width; in lpddr2_nvm_probe()
470 return -EINVAL; in lpddr2_nvm_probe()
481 WARN_ON(mtd_device_unregister(dev_get_drvdata(&pdev->dev))); in lpddr2_nvm_remove()
496 MODULE_DESCRIPTION("MTD driver for LPDDR2-NVM PCM memories");