1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/pkg/devices/lib/msc/include/msc-common.h Sun Feb 11 00:39:56 2024 +0100
1.3 @@ -0,0 +1,160 @@
1.4 +/*
1.5 + * MSC (MMC/SD controller) peripheral support.
1.6 + *
1.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#pragma once
1.26 +
1.27 +#include <l4/re/c/dma_space.h>
1.28 +#include <l4/sys/types.h>
1.29 +#include <stdint.h>
1.30 +
1.31 +
1.32 +
1.33 +#ifdef __cplusplus
1.34 +
1.35 +#include <l4/devices/hw_mmio_register_block.h>
1.36 +
1.37 +
1.38 +
1.39 +// MMC/SD structures.
1.40 +
1.41 +struct CID
1.42 +{
1.43 + uint16_t month:4, year:8, reserved:4;
1.44 + uint32_t serial;
1.45 + uint8_t revision;
1.46 + char name[5];
1.47 + uint16_t oem;
1.48 + uint8_t manufacturer;
1.49 +} __attribute__((packed));
1.50 +
1.51 +struct CSD
1.52 +{
1.53 + uint8_t reserved0:2, format:2, temp_write_prot:1, perm_write_prot:1, copy:1, format_group:1;
1.54 + uint16_t reserved1:5, write_block_partial:1, write_blocklen:4, write_time_factor:3,
1.55 + reserved2:2, write_prot_group_enable:1;
1.56 + uint64_t write_prot_group_size:7, erase_sector_size:7, erase_single_block_enable:1,
1.57 + device_size_multiplier:3, max_write_current_max:3, max_write_current_min:3,
1.58 + max_read_current_max:3, max_read_current_min:3, device_size:12,
1.59 + reserved3:2, dsr_implemented:1, read_block_misalign:1, write_block_misalign:1,
1.60 + read_block_partial:1, read_blocklen:4, card_command_classes:12;
1.61 + uint8_t tran_speed, data_read_access_time_2, data_read_access_time_1,
1.62 + reserved4:6, csd:2;
1.63 +} __attribute__((packed));
1.64 +
1.65 +
1.66 +
1.67 +// MMC/SD controller channel.
1.68 +
1.69 +class Msc_channel
1.70 +{
1.71 +protected:
1.72 + l4_addr_t _msc_start;
1.73 + Hw::Register_block<32> _regs;
1.74 + l4_cap_idx_t _irq;
1.75 +
1.76 + // Support eight CID/CSD entries of 120 bits and RCA entries of 16 bits.
1.77 +
1.78 + struct CID _cid[8];
1.79 + struct CSD _csd[8];
1.80 + uint16_t _rca[8], _current_rca;
1.81 + uint8_t _cards;
1.82 +
1.83 + // Utility methods.
1.84 +
1.85 + uint32_t get_field(uint32_t reg, uint32_t mask, uint8_t shift);
1.86 + void set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value);
1.87 +
1.88 + // Low-level operations.
1.89 +
1.90 + void ack_irq(uint32_t flags);
1.91 + void unmask_irq(uint32_t flags);
1.92 + void reset();
1.93 + void start_clock();
1.94 + void stop_clock();
1.95 +
1.96 + // Command properties.
1.97 +
1.98 + bool command_will_write(uint8_t index);
1.99 + bool command_with_data(uint8_t index);
1.100 + bool command_uses_busy(uint8_t index);
1.101 + uint8_t get_response_format(uint8_t index);
1.102 + uint8_t get_app_response_format(uint8_t index);
1.103 +
1.104 + // Command initiation.
1.105 +
1.106 + bool send_app_command(uint8_t index, uint32_t arg);
1.107 + bool send_command(uint8_t index, uint32_t arg);
1.108 + bool send_command(uint8_t index, uint32_t arg, uint8_t response_format,
1.109 + bool data, bool write, bool busy);
1.110 +
1.111 + // Response handling.
1.112 +
1.113 + bool have_response();
1.114 + void read_response(uint16_t *buffer, uint8_t units);
1.115 + bool wait_for_irq(uint32_t flags);
1.116 + bool wait_for_irq(uint32_t flags, unsigned int timeout);
1.117 +
1.118 + // Initialisation operations.
1.119 +
1.120 + bool check_sd();
1.121 + void init_sdio();
1.122 + void init_sdmem();
1.123 + void init_mmc();
1.124 + void identify_cards();
1.125 + void query_cards();
1.126 +
1.127 + // Transfer operations.
1.128 +
1.129 + uint32_t recv_data(l4re_dma_space_dma_addr_t paddr, uint32_t count);
1.130 + uint32_t send_data(l4re_dma_space_dma_addr_t paddr, uint32_t count);
1.131 +
1.132 + virtual uint32_t transfer(l4re_dma_space_dma_addr_t from_paddr,
1.133 + l4re_dma_space_dma_addr_t to_paddr,
1.134 + bool recv, uint32_t count) = 0;
1.135 +
1.136 +public:
1.137 + explicit Msc_channel(l4_addr_t msc_start, l4_addr_t start, l4_cap_idx_t irq);
1.138 +
1.139 + virtual ~Msc_channel();
1.140 +
1.141 + void enable();
1.142 +
1.143 + uint32_t get_status();
1.144 +
1.145 + uint32_t read_block(uint8_t card, l4re_dma_space_dma_addr_t paddr);
1.146 +};
1.147 +
1.148 +
1.149 +
1.150 +// MMC/SD controller device control.
1.151 +
1.152 +class Msc_chip
1.153 +{
1.154 +protected:
1.155 + l4_addr_t _msc_start, _start, _end;
1.156 +
1.157 + virtual unsigned int num_channels() = 0;
1.158 +
1.159 +public:
1.160 + explicit Msc_chip(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end);
1.161 +};
1.162 +
1.163 +#endif /* __cplusplus */