isp1760_field_set(udc->fields, HW_DP_PULLUP_CLEAR);
 }
 
+/*
+ * 60kb divided in:
+ * - 32 blocks @ 256  bytes
+ * - 20 blocks @ 1024 bytes
+ * -  4 blocks @ 8192 bytes
+ */
+static const struct isp1760_memory_layout isp176x_memory_conf = {
+       .blocks[0]              = 32,
+       .blocks_size[0]         = 256,
+       .blocks[1]              = 20,
+       .blocks_size[1]         = 1024,
+       .blocks[2]              = 4,
+       .blocks_size[2]         = 8192,
+
+       .ptd_num                = 32,
+       .payload_blocks         = 32 + 20 + 4,
+       .payload_area_size      = 0xf000,
+};
+
 static const struct regmap_range isp176x_hc_volatile_ranges[] = {
        regmap_reg_range(ISP176x_HC_USBCMD, ISP176x_HC_ATL_PTD_LASTPTD),
        regmap_reg_range(ISP176x_HC_BUFFER_STATUS, ISP176x_HC_MEMORY),
                udc->fields[i] = f;
        }
 
+       hcd->memory_layout = &isp176x_memory_conf;
+
        isp1760_init_core(isp);
 
        if (IS_ENABLED(CONFIG_USB_ISP1760_HCD) && !usb_disabled()) {
 
 /* memory management of the 60kb on the chip from 0x1000 to 0xffff */
 static void init_memory(struct isp1760_hcd *priv)
 {
-       int i, curr;
+       const struct isp1760_memory_layout *mem = priv->memory_layout;
+       int i, j, curr;
        u32 payload_addr;
 
        payload_addr = PAYLOAD_OFFSET;
-       for (i = 0; i < BLOCK_1_NUM; i++) {
-               priv->memory_pool[i].start = payload_addr;
-               priv->memory_pool[i].size = BLOCK_1_SIZE;
-               priv->memory_pool[i].free = 1;
-               payload_addr += priv->memory_pool[i].size;
-       }
-
-       curr = i;
-       for (i = 0; i < BLOCK_2_NUM; i++) {
-               priv->memory_pool[curr + i].start = payload_addr;
-               priv->memory_pool[curr + i].size = BLOCK_2_SIZE;
-               priv->memory_pool[curr + i].free = 1;
-               payload_addr += priv->memory_pool[curr + i].size;
-       }
 
-       curr = i;
-       for (i = 0; i < BLOCK_3_NUM; i++) {
-               priv->memory_pool[curr + i].start = payload_addr;
-               priv->memory_pool[curr + i].size = BLOCK_3_SIZE;
-               priv->memory_pool[curr + i].free = 1;
-               payload_addr += priv->memory_pool[curr + i].size;
+       for (i = 0, curr = 0; i < ARRAY_SIZE(mem->blocks); i++) {
+               for (j = 0; j < mem->blocks[i]; j++, curr++) {
+                       priv->memory_pool[curr + j].start = payload_addr;
+                       priv->memory_pool[curr + j].size = mem->blocks_size[i];
+                       priv->memory_pool[curr + j].free = 1;
+                       payload_addr += priv->memory_pool[curr + j].size;
+               }
        }
 
-       WARN_ON(payload_addr - priv->memory_pool[0].start > PAYLOAD_AREA_SIZE);
+       WARN_ON(payload_addr - priv->memory_pool[0].start >
+               mem->payload_area_size);
 }
 
 static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd)
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       const struct isp1760_memory_layout *mem = priv->memory_layout;
        int i;
 
        WARN_ON(qtd->payload_addr);
        if (!qtd->length)
                return;
 
-       for (i = 0; i < BLOCKS; i++) {
+       for (i = 0; i < mem->payload_blocks; i++) {
                if (priv->memory_pool[i].size >= qtd->length &&
                                priv->memory_pool[i].free) {
                        priv->memory_pool[i].free = 0;
 static void free_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd)
 {
        struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       const struct isp1760_memory_layout *mem = priv->memory_layout;
        int i;
 
        if (!qtd->payload_addr)
                return;
 
-       for (i = 0; i < BLOCKS; i++) {
+       for (i = 0; i < mem->payload_blocks; i++) {
                if (priv->memory_pool[i].start == qtd->payload_addr) {
                        WARN_ON(priv->memory_pool[i].free);
                        priv->memory_pool[i].free = 1;
 {
        qtd->data_buffer = databuffer;
 
-       if (len > MAX_PAYLOAD_SIZE)
-               len = MAX_PAYLOAD_SIZE;
        qtd->length = len;
 
        return qtd->length;
 static void packetize_urb(struct usb_hcd *hcd,
                struct urb *urb, struct list_head *head, gfp_t flags)
 {
+       struct isp1760_hcd *priv = hcd_to_priv(hcd);
+       const struct isp1760_memory_layout *mem = priv->memory_layout;
        struct isp1760_qtd *qtd;
        void *buf;
        int len, maxpacketsize;
                qtd = qtd_alloc(flags, urb, packet_type);
                if (!qtd)
                        goto cleanup;
+
+               if (len > mem->blocks_size[ISP176x_BLOCK_NUM - 1])
+                       len = mem->blocks_size[ISP176x_BLOCK_NUM - 1];
+
                this_qtd_len = qtd_fill(qtd, buf, len);
                list_add_tail(&qtd->qtd_list, head);
 
                         int irq, unsigned long irqflags,
                         struct device *dev)
 {
+       const struct isp1760_memory_layout *mem_layout = priv->memory_layout;
        struct usb_hcd *hcd;
        int ret;
 
 
        priv->hcd = hcd;
 
+       priv->memory_pool = kcalloc(mem_layout->payload_blocks,
+                                   sizeof(struct isp1760_memory_chunk),
+                                   GFP_KERNEL);
+       if (!priv->memory_pool) {
+               ret = -ENOMEM;
+               goto put_hcd;
+       }
+
+       priv->atl_slots = kcalloc(mem_layout->ptd_num,
+                                 sizeof(struct isp1760_slotinfo), GFP_KERNEL);
+       if (!priv->atl_slots) {
+               ret = -ENOMEM;
+               goto free_mem_pool;
+       }
+
+       priv->int_slots = kcalloc(mem_layout->ptd_num,
+                                 sizeof(struct isp1760_slotinfo), GFP_KERNEL);
+       if (!priv->int_slots) {
+               ret = -ENOMEM;
+               goto free_atl_slots;
+       }
+
        init_memory(priv);
 
        hcd->irq = irq;
 
        ret = usb_add_hcd(hcd, irq, irqflags);
        if (ret)
-               goto error;
+               goto free_int_slots;
 
        device_wakeup_enable(hcd->self.controller);
 
        return 0;
 
-error:
+free_int_slots:
+       kfree(priv->int_slots);
+free_atl_slots:
+       kfree(priv->atl_slots);
+free_mem_pool:
+       kfree(priv->memory_pool);
+put_hcd:
        usb_put_hcd(hcd);
        return ret;
 }
 
        usb_remove_hcd(priv->hcd);
        usb_put_hcd(priv->hcd);
+       kfree(priv->atl_slots);
+       kfree(priv->int_slots);
+       kfree(priv->memory_pool);
 }
 
 struct resource;
 struct usb_hcd;
 
-/*
- * 60kb divided in:
- * - 32 blocks @ 256  bytes
- * - 20 blocks @ 1024 bytes
- * -  4 blocks @ 8192 bytes
- */
-
-#define BLOCK_1_NUM 32
-#define BLOCK_2_NUM 20
-#define BLOCK_3_NUM 4
-
-#define BLOCK_1_SIZE 256
-#define BLOCK_2_SIZE 1024
-#define BLOCK_3_SIZE 8192
-#define BLOCKS (BLOCK_1_NUM + BLOCK_2_NUM + BLOCK_3_NUM)
-#define MAX_PAYLOAD_SIZE BLOCK_3_SIZE
-#define PAYLOAD_AREA_SIZE 0xf000
-
 struct isp1760_slotinfo {
        struct isp1760_qh *qh;
        struct isp1760_qtd *qtd;
 };
 
 /* chip memory management */
+#define ISP176x_BLOCK_NUM 3
+
+struct isp1760_memory_layout {
+       unsigned int blocks[ISP176x_BLOCK_NUM];
+       unsigned int blocks_size[ISP176x_BLOCK_NUM];
+
+       unsigned int ptd_num;
+       unsigned int payload_blocks;
+       unsigned int payload_area_size;
+};
+
 struct isp1760_memory_chunk {
        unsigned int start;
        unsigned int size;
        struct regmap           *regs;
        struct regmap_field     *fields[HC_FIELD_MAX];
 
+       const struct isp1760_memory_layout      *memory_layout;
+
        spinlock_t              lock;
-       struct isp1760_slotinfo atl_slots[32];
+       struct isp1760_slotinfo *atl_slots;
        int                     atl_done_map;
-       struct isp1760_slotinfo int_slots[32];
+       struct isp1760_slotinfo *int_slots;
        int                     int_done_map;
-       struct isp1760_memory_chunk memory_pool[BLOCKS];
+       struct isp1760_memory_chunk *memory_pool;
        struct list_head        qh_list[QH_END];
 
        /* periodic schedule support */