* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu-common.h"
+#include "hw.h"
#include "flash.h"
#include "irq.h"
-#include "sysemu.h"
-#include "block.h"
+#include "blockdev.h"
/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
#define PAGE_SHIFT 11
/* Fixed */
#define BLOCK_SHIFT (PAGE_SHIFT + 6)
-struct onenand_s {
+typedef struct {
uint32_t id;
int shift;
target_phys_addr_t base;
uint16_t intstatus;
uint16_t wpstatus;
- struct ecc_state_s ecc;
+ ECCState ecc;
int density_mask;
int secs;
int secs_cur;
int blocks;
uint8_t *blockwp;
-};
+} OneNANDState;
enum {
ONEN_BUF_BLOCK = 0,
void onenand_base_update(void *opaque, target_phys_addr_t new)
{
- struct onenand_s *s = (struct onenand_s *) opaque;
+ OneNANDState *s = (OneNANDState *) opaque;
s->base = new;
0xbe00 << s->shift,
(s->ram +(0x0200 << s->shift)) | IO_MEM_RAM);
if (s->iomemtype)
- cpu_register_physical_memory(s->base + (0xc000 << s->shift),
- 0x4000 << s->shift, s->iomemtype);
+ cpu_register_physical_memory_offset(s->base + (0xc000 << s->shift),
+ 0x4000 << s->shift, s->iomemtype, (0xc000 << s->shift));
}
void onenand_base_unmap(void *opaque)
{
- struct onenand_s *s = (struct onenand_s *) opaque;
+ OneNANDState *s = (OneNANDState *) opaque;
cpu_register_physical_memory(s->base,
0x10000 << s->shift, IO_MEM_UNASSIGNED);
}
-static void onenand_intr_update(struct onenand_s *s)
+static void onenand_intr_update(OneNANDState *s)
{
qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
}
/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
-static void onenand_reset(struct onenand_s *s, int cold)
+static void onenand_reset(OneNANDState *s, int cold)
{
memset(&s->addr, 0, sizeof(s->addr));
s->command = 0;
memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
if (s->bdrv && bdrv_read(s->bdrv, 0, s->boot[0], 8) < 0)
- cpu_abort(cpu_single_env, "%s: Loading the BootRAM failed.\n",
- __FUNCTION__);
+ hw_error("%s: Loading the BootRAM failed.\n", __FUNCTION__);
}
}
-static inline int onenand_load_main(struct onenand_s *s, int sec, int secn,
+static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
void *dest)
{
if (s->bdrv_cur)
return 0;
}
-static inline int onenand_prog_main(struct onenand_s *s, int sec, int secn,
+static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
void *src)
{
if (s->bdrv_cur)
return 0;
}
-static inline int onenand_load_spare(struct onenand_s *s, int sec, int secn,
+static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
void *dest)
{
uint8_t buf[512];
return 0;
}
-static inline int onenand_prog_spare(struct onenand_s *s, int sec, int secn,
+static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
void *src)
{
uint8_t buf[512];
return 0;
}
-static inline int onenand_erase(struct onenand_s *s, int sec, int num)
+static inline int onenand_erase(OneNANDState *s, int sec, int num)
{
/* TODO: optimise */
uint8_t buf[512];
return 0;
}
-static void onenand_command(struct onenand_s *s, int cmd)
+static void onenand_command(OneNANDState *s, int cmd)
{
int b;
int sec;
case 0x65: /* OTP Access */
s->intstatus |= ONEN_INT;
- s->bdrv_cur = 0;
+ s->bdrv_cur = NULL;
s->current = s->otp;
s->secs_cur = 1 << (BLOCK_SHIFT - 9);
s->addr[ONEN_BUF_BLOCK] = 0;
static uint32_t onenand_read(void *opaque, target_phys_addr_t addr)
{
- struct onenand_s *s = (struct onenand_s *) opaque;
- int offset = (addr - s->base) >> s->shift;
+ OneNANDState *s = (OneNANDState *) opaque;
+ int offset = addr >> s->shift;
switch (offset) {
case 0x0000 ... 0xc000:
- return lduw_le_p(s->boot[0] + (addr - s->base));
+ return lduw_le_p(s->boot[0] + addr);
case 0xf000: /* Manufacturer ID */
return (s->id >> 16) & 0xff;
case 0xff02: /* ECC Result of spare area data */
case 0xff03: /* ECC Result of main area data */
case 0xff04: /* ECC Result of spare area data */
- cpu_abort(cpu_single_env, "%s: imeplement ECC\n", __FUNCTION__);
+ hw_error("%s: imeplement ECC\n", __FUNCTION__);
return 0x0000;
}
static void onenand_write(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
- struct onenand_s *s = (struct onenand_s *) opaque;
- int offset = (addr - s->base) >> s->shift;
+ OneNANDState *s = (OneNANDState *) opaque;
+ int offset = addr >> s->shift;
int sec;
switch (offset) {
}
}
-static CPUReadMemoryFunc *onenand_readfn[] = {
+static CPUReadMemoryFunc * const onenand_readfn[] = {
onenand_read, /* TODO */
onenand_read,
onenand_read,
};
-static CPUWriteMemoryFunc *onenand_writefn[] = {
+static CPUWriteMemoryFunc * const onenand_writefn[] = {
onenand_write, /* TODO */
onenand_write,
onenand_write,
void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
{
- struct onenand_s *s = (struct onenand_s *) qemu_mallocz(sizeof(*s));
- int bdrv_index = drive_get_index(IF_MTD, 0, 0);
+ OneNANDState *s = (OneNANDState *) qemu_mallocz(sizeof(*s));
+ DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
uint32_t size = 1 << (24 + ((id >> 12) & 7));
void *ram;
s->shift = regshift;
s->intr = irq;
- s->rdy = 0;
+ s->rdy = NULL;
s->id = id;
s->blocks = size >> BLOCK_SHIFT;
s->secs = size >> 9;
s->blockwp = qemu_malloc(s->blocks);
s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
- s->iomemtype = cpu_register_io_memory(0, onenand_readfn,
- onenand_writefn, s);
- if (bdrv_index == -1)
+ s->iomemtype = cpu_register_io_memory(onenand_readfn,
+ onenand_writefn, s, DEVICE_NATIVE_ENDIAN);
+ if (!dinfo)
s->image = memset(qemu_malloc(size + (size >> 5)),
0xff, size + (size >> 5));
else
- s->bdrv = drives_table[bdrv_index].bdrv;
+ s->bdrv = dinfo->bdrv;
s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
0xff, (64 + 2) << PAGE_SHIFT);
- s->ram = qemu_ram_alloc(0xc000 << s->shift);
- ram = phys_ram_base + s->ram;
+ s->ram = qemu_ram_alloc(NULL, "onenand.ram", 0xc000 << s->shift);
+ ram = qemu_get_ram_ptr(s->ram);
s->boot[0] = ram + (0x0000 << s->shift);
s->boot[1] = ram + (0x8000 << s->shift);
s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
return s;
}
+
+void *onenand_raw_otp(void *opaque)
+{
+ OneNANDState *s = (OneNANDState *) opaque;
+
+ return s->otp;
+}