blob: a987b4a354ce0dcc3cdf93227a177f672825e311 [file] [log] [blame]
/*
* Aml nftl dev
*
* (C) 2012 8
*/
#include "../include/amlnf_dev.h"
#include "partition_table.h"
int boot_device_flag = 0;
struct aml_nand_device *aml_nand_dev = NULL;
int is_phydev_off_adjust(void)
{
int ret = 0;
#ifdef NAND_ADJUST_PART_TABLE
ret = 1;
#endif
return ret ;
}
int get_adjust_block_num(void)
{
int ret = 0;
#ifdef NAND_ADJUST_PART_TABLE
ret = ADJUST_BLOCK_NUM;
#endif
return ret ;
}
int amlnf_get_logicdev(struct amlnf_logicdev_t *amlnf_logicdev)
{
#ifndef AML_NAND_UBOOT
mutex_lock(&amlnf_logicdev->lock);
#endif
return 0;
}
int amlnf_free_logicdev(struct amlnf_logicdev_t *amlnf_logicdev)
{
#ifndef AML_NAND_UBOOT
mutex_unlock(&amlnf_logicdev->lock);
#endif
return 0;
}
/*****************************************************************************
*Name :
*Description :
*Parameter :
*Return :
*Note :
*****************************************************************************/
#ifndef AML_NAND_UBOOT
static struct class_attribute phydev_class_attrs[] = {
__ATTR(info, S_IRUGO | S_IWUSR, show_nand_info, NULL),
__ATTR(verify, S_IRUGO | S_IWUSR, NULL, verify_nand_page),
__ATTR(dump, S_IRUGO | S_IWUSR, NULL, dump_nand_page),
__ATTR(bbt_table, S_IRUGO | S_IWUSR, NULL, show_bbt_table),
__ATTR(test_sync_flag, S_IRUGO | S_IWUSR, NULL, change_test_sync_flag),
__ATTR(page_read, S_IRUGO | S_IWUSR, NULL, nand_page_read),
__ATTR(page_write, S_IRUGO | S_IWUSR, NULL, nand_page_write),
__ATTR(version, S_IRUGO | S_IWUSR, show_amlnf_version_info, NULL),
__ATTR_NULL
};
#if 0
static struct class_attribute logicdev_class_attrs[] = {
__ATTR(part, S_IRUGO , show_part_struct, NULL),
__ATTR(list, S_IRUGO , show_list, NULL),
__ATTR(gcall, S_IRUGO , do_gc_all, NULL),
__ATTR(gcone, S_IRUGO , do_gc_one, NULL),
__ATTR(test, S_IRUGO | S_IWUSR , NULL, do_test),
__ATTR_NULL
};
static struct class_attribute nfdev_class_attrs[] = {
__ATTR(debug, S_IRUGO , nfdev_debug, NULL),
__ATTR_NULL
};
#endif
#if 0
static struct class phydev_class = {
.name = "amlphydev",
.owner = THIS_MODULE,
.suspend = phydev_cls_suspend,
.resume = phydev_cls_resume,
};
#endif
int amlnf_pdev_register(struct amlnand_phydev *phydev)
{
int ret = 0;
/* phydev->dev.class = &phydev_class; */
dev_set_name(&phydev->dev, phydev->name, 0);
dev_set_drvdata(&phydev->dev, phydev);
ret = device_register(&phydev->dev);
if (ret != 0) {
aml_nand_msg("device register failed for %s", phydev->name);
aml_nand_free(phydev);
goto exit_error0;
}
phydev->cls.name =
aml_nand_malloc(strlen((const char *)phydev->name)+8);
snprintf((char *)phydev->cls.name,
(MAX_DEVICE_NAME_LEN+8),
"%s%s",
"phy_",
(char *)(phydev->name));
phydev->cls.class_attrs = phydev_class_attrs;
ret = class_register(&phydev->cls);
if (ret) {
aml_nand_msg("class register nand_class fail for %s",
phydev->name);
goto exit_error1;
}
return 0;
exit_error1:
aml_nand_free(phydev->cls.name);
exit_error0:
return ret;
}
static int amlnf_blk_open(struct block_device *bdev, fmode_t mode)
{
return 0;
}
static void amlnf_blk_release(struct gendisk *disk, fmode_t mode)
{
return;
}
static int amlnf_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
return 0;
}
static int amlnf_blk_ioctl(struct block_device *bdev, fmode_t mode,
u32 cmd, u32 arg)
{
return 0;
}
static const struct block_device_operations amlnf_blk_ops = {
.owner = THIS_MODULE,
.open = amlnf_blk_open,
.release = amlnf_blk_release,
.ioctl = amlnf_blk_ioctl,
.getgeo = amlnf_blk_getgeo,
};
#define blk_queue_plugged(q) test_bit(18, &(q)->queue_flags)
/*****************************************************************************
*Name :
*Description :
*Parameter :
*Return :
*Note : for kernel; for boot is in logic\aml_nftl_init.c
*****************************************************************************/
int amlnf_logic_init(u32 flag)
{
struct amlnand_phydev *phydev = NULL;
int ret = 0;
aml_nand_msg("amlnand_add_nftl:");
/* amlnand_show_dev_partition(aml_chip); */
list_for_each_entry(phydev, &nphy_dev_list, list) {
if (phydev == NULL)
break;
if (strncmp((char *)phydev->name,
NAND_BOOT_NAME,
strlen((const char *)NAND_BOOT_NAME))) {
ret = add_ntd_partitions(phydev);
if (ret < 0) {
aml_nand_msg("nand add nftl failed");
goto exit_error;
}
}
if (!strncmp((char *)phydev->name,
NAND_BOOT_NAME,
strlen((const char *)NAND_BOOT_NAME))) {
ret = boot_device_register(phydev);
if (ret < 0) {
aml_nand_msg("boot device registe failed");
goto exit_error;
}
}
}
exit_error:
return ret;
}
static ssize_t nand_version_get(struct class *class,
struct class_attribute *attr,
char *buf)
{
sprintf(buf, "%d", DRV_PHY_VERSION);
return 0;
}
static void show_partition_table(struct partitions *table)
{
int i = 0;
struct partitions *par_table = NULL;
aml_nand_msg("show partition table:");
for (i = 0; i < MAX_PART_NUM; i++) {
par_table = &table[i];
if (par_table->size == -1) {
aml_nand_msg("part: %d, name: %10s, size: %-4s",
i,
par_table->name,
"end");
break;
} else
aml_nand_msg("part: %d, name : %10s, size : %-4llx",
i,
par_table->name,
par_table->size);
}
return;
}
static ssize_t nand_part_table_get(struct class *class,
struct class_attribute *attr, char *buf)
{
struct amlnand_phydev *phydev = NULL;
struct amlnand_chip *aml_chip = NULL;
struct nand_config *config = NULL;
struct dev_para *dev_paramt = NULL;
struct partitions *part_table = NULL;
int i = 0, j = 0, k = 0, m = 0, tmp_num = 0;
int device_num;
device_num = (aml_chip->h_cache_dev)? 3 : 2;
list_for_each_entry(phydev, &nphy_dev_list, list) {
if ((phydev != NULL)
&& (!strncmp((char *)phydev->name,
NAND_CODE_NAME,
strlen((const char *)NAND_CODE_NAME))))
break;
}
aml_chip = (struct amlnand_chip *)phydev->priv;
config = aml_chip->config_ptr;
part_table = aml_nand_malloc(MAX_PART_NUM*sizeof(struct partitions));
if (!part_table) {
aml_nand_msg("nand_part_table_get : malloc failed");
return 0;
}
memset(part_table, 0x0, MAX_PART_NUM*sizeof(struct partitions));
if (boot_device_flag == 1) {
i += 1;
tmp_num = i;
}
for (; i < device_num + 1; i++) {
dev_paramt = &config->dev_para[i];
if ((!strncmp((char *)dev_paramt->name,
NAND_CODE_NAME,
strlen((const char *)NAND_CODE_NAME)))) {
for (j = 0; j < dev_paramt->nr_partitions; j++) {
memcpy(&(part_table[j].name),
dev_paramt->partitions[j].name,
MAX_NAND_PART_NAME_LEN);
part_table[j].size =
dev_paramt->partitions[j].size;
part_table[j].offset =
dev_paramt->partitions[j].offset;
part_table[j].mask_flags =
dev_paramt->partitions[j].mask_flags;
/*
aml_nand_msg("CODE: partiton name %s, size %llx,
offset %llx maskflag %d",
part_table[j].name,
part_table[j].size,
part_table[j].offset,
part_table[j].mask_flags);
*/
}
break;
}
}
i = tmp_num;
for (; i < device_num + 1; i++) {
dev_paramt = &config->dev_para[i];
/*
aml_nand_msg("cache : dev_paramt name %s ",dev_paramt->name);
*/
if ((!strncmp((char *)dev_paramt->name,
NAND_CACHE_NAME,
strlen((const char *)NAND_CACHE_NAME)))) {
k = j++;
for (j = 0; j < dev_paramt->nr_partitions; k++, j++) {
memcpy(&(part_table[k].name),
dev_paramt->partitions[j].name,
MAX_NAND_PART_NAME_LEN);
part_table[k].size =
dev_paramt->partitions[j].size;
part_table[k].offset =
dev_paramt->partitions[j].offset;
part_table[k].mask_flags =
dev_paramt->partitions[j].mask_flags;
/*
aml_nand_msg("CODE: partiton name %s,size %llx,
offset %llx maskflag %d",
part_table[k].name,
part_table[k].size,
part_table[k].offset,
part_table[k].mask_flags);
*/
}
break;
}
}
i = tmp_num;
for (; i < device_num + 1; i++) {
dev_paramt = &config->dev_para[i];
/*
aml_nand_msg("dev_paramt name %s ",dev_paramt->name);
*/
if ((!strncmp((char *)dev_paramt->name,
NAND_DATA_NAME,
strlen((const char *)NAND_DATA_NAME)))) {
m = k++;
for (j = 0; j < dev_paramt->nr_partitions; j++) {
memcpy(&(part_table[m].name),
dev_paramt->partitions[j].name,
MAX_NAND_PART_NAME_LEN);
part_table[m].size =
dev_paramt->partitions[j].size;
part_table[m].offset =
dev_paramt->partitions[j].offset;
part_table[m].mask_flags =
dev_paramt->partitions[j].mask_flags;
/*
aml_nand_msg("CODE:partiton name %s,size %llx,
offset %llx maskflag %d",
part_table[m].name,
part_table[m].size,
part_table[m].offset,
part_table[m].mask_flags);
*/
}
break;
}
}
show_partition_table(part_table);
memcpy(buf, part_table, MAX_PART_NUM*sizeof(struct partitions));
kfree(part_table);
part_table = NULL;
return 0;
}
static ssize_t store_device_flag_get(struct class *class,
struct class_attribute *attr, char *buf)
{
sprintf(buf, "%d", boot_device_flag);
return 0;
}
static struct class_attribute aml_version =
__ATTR(version, S_IRUGO, nand_version_get, NULL);
static struct class_attribute aml_part_table =
__ATTR(part_table, S_IRUGO, nand_part_table_get, NULL);
static struct class_attribute aml_store_device =
__ATTR(store_device, S_IRUGO, store_device_flag_get, NULL);
#endif /* AML_NAND_UBOOT */
/*****************************************************************************
*Name :
*Description :
*Parameter :
*Return :
*Note :
*****************************************************************************/
int amlnf_dev_init(u32 flag)
{
#ifndef AML_NAND_UBOOT
struct amlnand_phydev *phydev = NULL;
/* struct amlnf_dev* nf_dev = NULL; */
struct class *aml_store_class = NULL;
int ret = 0;
list_for_each_entry(phydev, &nphy_dev_list, list) {
if ((phydev != NULL)
&& (strncmp((char *)phydev->name,
NAND_BOOT_NAME,
strlen((const char *)NAND_BOOT_NAME)))) {
ret = amlnf_pdev_register(phydev);
if (ret < 0) {
aml_nand_msg("nand add nftl failed");
goto exit_error0;
}
}
}
aml_store_class = class_create(THIS_MODULE, "aml_store");
if (IS_ERR(aml_store_class)) {
aml_nand_msg("amlnf_dev_init : class cread failed");
ret = -1;
goto exit_error0;
}
ret = class_create_file(aml_store_class, &aml_version);
if (ret) {
aml_nand_msg("amlnf_dev_init : cannot create sysfs file : ");
goto out_class1;
}
ret = class_create_file(aml_store_class, &aml_part_table);
if (ret) {
aml_nand_msg("amlnf_dev_init : cannot create sysfs file : ");
goto out_class2;
}
ret = class_create_file(aml_store_class, &aml_store_device);
if (ret) {
aml_nand_msg("amlnf_dev_init : cannot create sysfs file : ");
goto out_class3;
}
#endif
return 0;
#ifndef AML_NAND_UBOOT
out_class3:
class_remove_file(aml_store_class, &aml_part_table);
out_class2:
class_remove_file(aml_store_class, &aml_version);
out_class1:
class_destroy(aml_store_class);
exit_error0:
return ret;
#endif
}
#ifdef CONFIG_OF
static const struct of_device_id amlogic_nand_dt_match[] = {
{ .compatible = "amlogic,aml_nand",
},
{},
};
/*
static inline struct
aml_nand_device *aml_get_driver_data(struct platform_device *pdev)
{
if (pdev->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(amlogic_nand_dt_match, pdev->dev.of_node);
return (struct aml_nand_device *)match->data;
}
return NULL;
}
static int get_nand_platform(struct aml_nand_device *aml_nand_dev,
struct platform_device *pdev)
{
int ret;
int plat_num = 0;
struct device_node *np = pdev->dev.of_node;
if (pdev->dev.of_node) {
of_node_get(np);
ret = of_property_read_u32(np, "plat-num", &plat_num);
if (ret) {
aml_nand_msg("%s:%d,please config plat-num item\n",
__func__,
__LINE__);
return -1;
}
}
aml_nand_dbg("plat_num %d ", plat_num);
return 0;
}
*/
#endif /* CONFIG_OF */
/***
*boot_device_flag = 0 ; indicate spi+nand boot
*boot_device_flag = 1; indicate nand boot
***/
#if 1
int poc_cfg_prase(void)
{
int boot_flag;
u32 cpu_type, poc_value;
poc_value =
amlnf_read_reg32(aml_nand_dev->platform_data->poc_reg);
cpu_type = get_cpu_type();
if (cpu_type == MESON_CPU_MAJOR_ID_GX) {
poc_value = (poc_value >> 6) & 0x03;
} else if (cpu_type >= MESON_CPU_MAJOR_ID_M8)
poc_value = ((((poc_value >> 0x09) & 0x01) << 2) |
((poc_value >> 6) & 0x03));
else
poc_value = (poc_value & 0x07);
if (cpu_type == MESON_CPU_MAJOR_ID_GX) {
if (poc_value & 0x2)
boot_flag = SPI_BOOT_FLAG;
else
boot_flag = NAND_BOOT_FLAG; //fixme, ...
} else if (cpu_type > MESON_CPU_MAJOR_ID_M8) {
if (poc_value == 0x05)
boot_flag = SPI_BOOT_FLAG;
if ((poc_value == 0x03) || (poc_value == 0x01))
boot_flag = EMMC_BOOT_FLAG;
} else {
if ((poc_value == 0x05) || (poc_value == 0x04))
boot_flag = SPI_BOOT_FLAG;
if (poc_value == 0x03)
boot_flag = EMMC_BOOT_FLAG;
}
if ((poc_value == 0x07) || (poc_value == 0x06))
boot_flag = NAND_BOOT_FLAG;
if (poc_value == 0x00)
boot_flag = EMMC_BOOT_FLAG;
return boot_flag;
}
int check_storage_device(void)
{
int value = -1, poc_cfg = -1;
poc_cfg = poc_cfg_prase();
value = boot_device_flag;
if ((value == 0)
|| (value == SPI_NAND_FLAG)
|| (value == NAND_BOOT_FLAG)) {
if ((value == 0) || (value == -1)) {
if (poc_cfg == NAND_BOOT_FLAG)
boot_device_flag = 1;
else if (poc_cfg == EMMC_BOOT_FLAG)
boot_device_flag = -1;
else if (poc_cfg == SPI_BOOT_FLAG)
boot_device_flag = 0;
else if (poc_cfg == CARD_BOOT_FLAG)
boot_device_flag = 1;
} else if (value == SPI_NAND_FLAG)
boot_device_flag = 0;
else
boot_device_flag = 1;
} else
boot_device_flag = -1;
boot_device_flag = 1; //fixme, debug code....
aml_nand_msg("boot_device_flag : %d", boot_device_flag);
if ((boot_device_flag == 0) || (boot_device_flag == 1))
return 0;
else {
boot_device_flag = value;
return -NAND_FAILED;
}
}
EXPORT_SYMBOL(check_storage_device);
#endif
#ifndef AML_NAND_UBOOT
static int __init get_storage_device(char *str)
{
int value = -1;
if (kstrtoul(str, 16, (u32 *)&value))
return -EINVAL;
/*value = strtoul(str, NULL, 16);*/
aml_nand_msg("get storage device: storage %s", str);
aml_nand_msg("value=%d", value);
boot_device_flag = value;
return 0;
}
early_param("storage", get_storage_device);
static int amlnf_get_resource(struct platform_device *pdev)
{
struct resource *res_mem, *res_irq;
int size;
/*
getting Nand Platform Data that are set in dts files by of_xxx functions
*/
#ifdef CONFIG_OF
/*
pdev->dev.platform_data = aml_get_driver_data(pdev);
aml_nand_msg("===========================================");
aml_nand_msg("%s:%d,nand device tree ok,dev-name:%s\n",
__func__,
__LINE__,
dev_name(&pdev->dev));
*/
#endif
/*
ret = get_nand_platform(pdev->dev.platform_data, pdev);
*/
/*aml_nand_dev = pdev->dev.platform_data;*/
aml_nand_dev = kzalloc(sizeof(struct aml_nand_device), GFP_KERNEL);
if (!aml_nand_dev) {
aml_nand_msg("aml_nand_dev not exist\n");
return -ENODEV;
}
aml_nand_dev->platform_data =
kzalloc(sizeof(struct amlnf_platform_data), GFP_KERNEL);
if (!aml_nand_dev->platform_data) {
aml_nand_msg("malloc platform data fail\n");
return -ENOMEM;
}
/*mapping PORT CONFIG register address*/
aml_nand_dev->platform_data->poc_reg =
devm_ioremap_nocache(&pdev->dev, POC_CONFIG_REG, sizeof(int));
if (aml_nand_dev->platform_data->poc_reg == NULL) {
dev_err(&pdev->dev, "ioremap External Port Config IO fail\n");
return -ENOMEM;
}
aml_nand_msg("poc_reg = 0x%0x\n",
(u32)aml_nand_dev->platform_data->poc_reg);
/*getting nand platform device IORESOURCE_MEM*/
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res_mem) {
dev_err(&pdev->dev, "cannot obtain I/O memory region");
return -ENODEV;
}
size = resource_size(res_mem);
aml_nand_msg("%s : %0x %0x\n", __func__, res_mem->start , size);
/*mapping Nand Flash Controller register address*/
/*request mem erea*/
if (!devm_request_mem_region(&pdev->dev,
res_mem->start,
size,
dev_name(&pdev->dev))) {
dev_err(&pdev->dev, "Memory region busy\n");
return -EBUSY;
}
/*mapping IO, nocache*/
aml_nand_dev->platform_data->nf_reg_base =
devm_ioremap_nocache(&pdev->dev,
res_mem->start,
size);
if (aml_nand_dev->platform_data->nf_reg_base == NULL) {
dev_err(&pdev->dev, "ioremap Nand Flash IO fail\n");
return -ENOMEM;
}
/*mapping external Clock register address of Nand Flash Controller*/
aml_nand_dev->platform_data->ext_clk_reg =
devm_ioremap_nocache(&pdev->dev,
NAND_CLK_CNTL,
sizeof(int));
if (aml_nand_dev->platform_data->ext_clk_reg == NULL) {
dev_err(&pdev->dev, "ioremap External Nand Clock IO fail\n");
return -ENOMEM;
}
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res_irq) {
dev_err(&pdev->dev, "irq res get fail\n");
return -ENODEV;
}
aml_nand_dev->platform_data->irq = res_irq->start;
return 0;
}
#else /* AML_NAND_UBOOT */
/*fixme, yyh*/
static int amlnf_get_resource(struct platform_device *pdev)
{
/*TODO: */
aml_nand_dev = kzalloc(sizeof(struct aml_nand_device), GFP_KERNEL);
if (!aml_nand_dev) {
aml_nand_msg("aml_nand_dev not exist\n");
return -ENODEV;
}
aml_nand_dev->platform_data =
kzalloc(sizeof(struct amlnf_platform_data), GFP_KERNEL);
if (!aml_nand_dev->platform_data) {
aml_nand_msg("malloc platform data fail\n");
return -ENOMEM;
}
aml_nand_dbg("nand io resources:\n");
aml_nand_dev->platform_data->poc_reg = (volatile uint32_t *)P_ASSIST_POR_CONFIG;
aml_nand_dbg("poc_reg = %p\n",
aml_nand_dev->platform_data->poc_reg);
aml_nand_dev->platform_data->nf_reg_base = (volatile uint32_t *)NAND_BASE_APB;
aml_nand_dbg("nf_reg_base = %p\n",
aml_nand_dev->platform_data->nf_reg_base);
aml_nand_dev->platform_data->ext_clk_reg = (volatile uint32_t *)NAND_CLK_CNTL;
aml_nand_dbg("ext_clk_reg = %p\n",
aml_nand_dev->platform_data->ext_clk_reg);
return 0;
}
#endif /* AML_NAND_UBOOT */
#ifdef AML_NAND_UBOOT
extern struct list_head nlogic_dev_list;
#endif /* AML_NAND_UBOOT */
static int _amlnf_init(struct platform_device *pdev, u32 flag)
{
int ret = 0;
INIT_LIST_HEAD (&nphy_dev_list);
INIT_LIST_HEAD (&nlogic_dev_list);
INIT_LIST_HEAD (&nf_dev_list);
PHY_NAND_LINE
/*Nand physic init*/
/*Amlogic Nand Flash Controller init and Nand chip init ......*/
/*Scan or Build table,fbbt ,bbt, key and so on*/
/*Creating physical partition, offset and size*/
ret = amlnf_phy_init(flag, pdev);
if (ret) {
aml_nand_msg("nandphy_init failed and ret=0x%x", ret);
if (ret == -NAND_FAILED) {
ret = -1; // controller failed
}else if(ret == -NAND_SHIPPED_BADBLOCK_FAILED){
ret = NAND_SHIPPED_BADBLOCK_FAILED;
}
else if (ret == -NAND_DETECT_DTB_FAILED)
{
ret = NAND_DETECT_DTB_FAILED;
}
else{
ret = 1;
}
goto exit_error0;
}
PHY_NAND_LINE
//only read id, quit myself.
if (flag == NAND_SCAN_ID_INIT)
goto exit_error0;
PHY_NAND_LINE
/*Nand logic init*/
ret = amlnf_logic_init(flag);
if (ret < 0) {
aml_nand_msg("amlnf_add_nftl failed and ret=0x%x", ret);
goto exit_error0;
}
PHY_NAND_LINE
ret = amlnf_dev_init(flag);
if (ret < 0) {
aml_nand_msg("amlnf_add_nftl failed and ret=0x%x", ret);
goto exit_error0;
}
PHY_NAND_LINE
exit_error0:
return ret; /* fixme, */
}
#ifndef AML_NAND_UBOOT
static int amlnf_driver_probe(struct platform_device *pdev)
#else
int amlnf_init(u32 flag)
#endif /* AML_NAND_UBOOT */
{
int ret = 0;
#ifndef AML_NAND_UBOOT
u32 flag = 0;
#else
struct platform_device plat_dev;
struct platform_device *pdev = &plat_dev;
#endif /* AML_NAND_UBOOT */
PHY_NAND_LINE
ret = amlnf_get_resource(pdev);
if (ret < 0) {
aml_nand_msg("get resource fail!");
return 0;
}
PHY_NAND_LINE
/*judge if it is nand boot device*/
ret = check_storage_device();
if (ret < 0) {
aml_nand_msg("do not init nand");
return 0;
}
PHY_NAND_LINE
/*Initializing Nand Flash*/
ret = _amlnf_init(pdev, flag);
PHY_NAND_LINE
return ret;
}
#ifdef AML_NAND_UBOOT
int amlnf_exit(unsigned flag)
#else
static int amlnf_exit(struct platform_device *pdev)
#endif
{
extern void amlnf_phy_exit(void);
extern void amlnf_logic_exit(void);
amlnf_phy_exit();
amlnf_logic_exit();
aml_nand_msg("amlnf_exit : ok");
return 0;
}
#ifndef AML_NAND_UBOOT
static int amlnf_driver_remove(struct platform_device *pdev)
{
return 0;
}
static void amlnf_driver_shutdown(struct platform_device *pdev)
{
struct amlnand_phydev *phy_dev = NULL;
struct amlnand_chip *aml_chip = NULL;
if (check_storage_device() < 0) {
aml_nand_msg("without nand");
return;
}
list_for_each_entry(phy_dev, &nphy_dev_list, list) {
if (phy_dev) {
aml_chip = (struct amlnand_chip *)phy_dev->priv;
amlnand_get_device(aml_chip, CHIP_SHUTDOWN);
phy_dev->option |= NAND_SHUT_DOWN;
amlnand_release_device(aml_chip);
}
}
return;
}
/* driver device registration */
static struct platform_driver amlnf_driver = {
.probe = amlnf_driver_probe,
.remove = amlnf_driver_remove,
.shutdown = amlnf_driver_shutdown,
.driver = {
.name = DRV_AMLNFDEV_NAME,
.owner = THIS_MODULE,
.of_match_table = amlogic_nand_dt_match,
},
};
static int __init amlnf_module_init(void)
{
return platform_driver_register(&amlnf_driver);
}
static void __exit amlnf_module_exit(void)
{
platform_driver_unregister(&amlnf_driver);
}
module_init(amlnf_module_init);
module_exit(amlnf_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AML NAND TEAM");
MODULE_DESCRIPTION("aml nand flash driver");
#endif /* AML_NAND_UBOOT */
#ifdef AML_NAND_UBOOT
struct amlnand_phydev *aml_phy_get_dev(char * name)
{
struct amlnand_phydev * phy_dev = NULL;
list_for_each_entry(phy_dev, &nphy_dev_list, list){
if (!strncmp((char*)phy_dev->name, name, MAX_DEVICE_NAME_LEN)) {
aml_nand_dbg("nand get phy dev %s ",name);
return phy_dev;
}
}
aml_nand_msg("nand get phy dev %s failed",name);
return NULL;
}
struct amlnf_dev* aml_nftl_get_dev(char * name)
{
struct amlnf_dev * nf_dev = NULL;
list_for_each_entry(nf_dev, &nf_dev_list, list){
if (!strcmp((char*)nf_dev->name, name)) {
aml_nand_dbg("nand get nftl dev %s ",name);
return nf_dev;
}
}
aml_nand_msg("nand get nftl dev %s failed",name);
return NULL;
}
void show_ldev_list(void)
{
struct amlnf_dev * nf_dev = NULL;
int i = 0;
printf("logic partitions table, in sectors\n");
list_for_each_entry(nf_dev, &nf_dev_list, list) {
printf("%d: %s: 0x%llx 0x%llx\n", i++, (char*)nf_dev->name,
nf_dev->offset_sector, nf_dev->size_sector);
}
}
int amlnf_logicdev_mis_init(struct amlnf_logicdev_t *amlnf_logicdev)
{
return 0;
}
#endif